Streamline context menus of regular tray application and Plasmoid
* Support triggering actions via the context menu in the regular tray like it is already possible in the Plasmoid * Support copying via the context menu in the Plasmoid like it is already possible in the regular tray * Reduce repetition of coding patterns using templates
This commit is contained in:
parent
7cf98e97a7
commit
aac87621dc
|
@ -33,11 +33,12 @@ public Q_SLOTS:
|
|||
QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override;
|
||||
QModelIndex parent(const QModelIndex &child) const override;
|
||||
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
|
||||
QVariant data(const QModelIndex &index, int role) const override;
|
||||
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
||||
bool setData(const QModelIndex &index, const QVariant &value, int role) override;
|
||||
int rowCount(const QModelIndex &parent) const override;
|
||||
int columnCount(const QModelIndex &parent) const override;
|
||||
const SyncthingDev *devInfo(const QModelIndex &index) const;
|
||||
const SyncthingDev *info(const QModelIndex &index) const;
|
||||
|
||||
private Q_SLOTS:
|
||||
void devStatusChanged(const SyncthingDev &, int index);
|
||||
|
@ -50,6 +51,11 @@ private:
|
|||
const std::vector<SyncthingDev> &m_devs;
|
||||
};
|
||||
|
||||
inline const SyncthingDev *SyncthingDeviceModel::info(const QModelIndex &index) const
|
||||
{
|
||||
return devInfo(index);
|
||||
}
|
||||
|
||||
} // namespace Data
|
||||
|
||||
#endif // DATA_SYNCTHINGDEVICEMODEL_H
|
||||
|
|
|
@ -34,11 +34,12 @@ public Q_SLOTS:
|
|||
QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override;
|
||||
QModelIndex parent(const QModelIndex &child) const override;
|
||||
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
|
||||
QVariant data(const QModelIndex &index, int role) const override;
|
||||
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
||||
bool setData(const QModelIndex &index, const QVariant &value, int role) override;
|
||||
int rowCount(const QModelIndex &parent) const override;
|
||||
int columnCount(const QModelIndex &parent) const override;
|
||||
const SyncthingDir *dirInfo(const QModelIndex &index) const;
|
||||
const SyncthingDir *info(const QModelIndex &index) const;
|
||||
|
||||
private Q_SLOTS:
|
||||
void dirStatusChanged(const SyncthingDir &dir, int index);
|
||||
|
@ -55,6 +56,11 @@ private:
|
|||
std::vector<int> m_rowCount;
|
||||
};
|
||||
|
||||
inline const SyncthingDir *SyncthingDirectoryModel::info(const QModelIndex &index) const
|
||||
{
|
||||
return dirInfo(index);
|
||||
}
|
||||
|
||||
} // namespace Data
|
||||
|
||||
Q_DECLARE_METATYPE(QModelIndex)
|
||||
|
|
|
@ -27,12 +27,13 @@ public Q_SLOTS:
|
|||
QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override;
|
||||
QModelIndex parent(const QModelIndex &child) const override;
|
||||
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
|
||||
QVariant data(const QModelIndex &index, int role) const override;
|
||||
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
||||
bool setData(const QModelIndex &index, const QVariant &value, int role) override;
|
||||
int rowCount(const QModelIndex &parent) const override;
|
||||
int columnCount(const QModelIndex &parent) const override;
|
||||
const SyncthingDir *dirInfo(const QModelIndex &index) const;
|
||||
const SyncthingItemDownloadProgress *progressInfo(const QModelIndex &index) const;
|
||||
QPair<const SyncthingDir *, const SyncthingItemDownloadProgress *> info(const QModelIndex &index) const;
|
||||
unsigned int pendingDownloads() const;
|
||||
bool singleColumnMode() const;
|
||||
void setSingleColumnMode(bool singleColumnModeEnabled);
|
||||
|
@ -62,6 +63,11 @@ private:
|
|||
bool m_singleColumnMode;
|
||||
};
|
||||
|
||||
inline QPair<const SyncthingDir *, const SyncthingItemDownloadProgress *> SyncthingDownloadModel::info(const QModelIndex &index) const
|
||||
{
|
||||
return qMakePair(dirInfo(index), progressInfo(index));
|
||||
}
|
||||
|
||||
inline unsigned int SyncthingDownloadModel::pendingDownloads() const
|
||||
{
|
||||
return m_pendingDownloads;
|
||||
|
|
|
@ -23,6 +23,8 @@ Item {
|
|||
delegate: TopLevelItem {
|
||||
id: item
|
||||
width: deviceView.width
|
||||
readonly property string devName: name
|
||||
readonly property string devId: devId
|
||||
property alias resumePauseButton: resumePauseButton
|
||||
|
||||
ColumnLayout {
|
||||
|
@ -95,6 +97,19 @@ Item {
|
|||
resumePauseItem.icon = item.resumePauseButton.icon
|
||||
}
|
||||
|
||||
PlasmaComponents.MenuItem {
|
||||
text: qsTr("Copy name")
|
||||
icon: "edit-copy"
|
||||
onClicked: deviceView.copyCurrentItemData("devName")
|
||||
}
|
||||
PlasmaComponents.MenuItem {
|
||||
text: qsTr("Copy ID")
|
||||
icon: "edit-copy"
|
||||
onClicked: deviceView.copyCurrentItemData("devId")
|
||||
}
|
||||
PlasmaComponents.MenuItem {
|
||||
separator: true
|
||||
}
|
||||
PlasmaComponents.MenuItem {
|
||||
id: resumePauseItem
|
||||
text: qsTr("Pause")
|
||||
|
|
|
@ -31,6 +31,8 @@ ColumnLayout {
|
|||
delegate: TopLevelItem {
|
||||
id: item
|
||||
width: directoryView.width
|
||||
readonly property string dirName: name
|
||||
readonly property string dirPath: path
|
||||
property alias errorsButton: errorsButton
|
||||
property alias rescanButton: rescanButton
|
||||
property alias resumePauseButton: resumePauseButton
|
||||
|
@ -139,9 +141,22 @@ ColumnLayout {
|
|||
resumePauseItem.icon = item.resumePauseButton.icon
|
||||
}
|
||||
|
||||
PlasmaComponents.MenuItem {
|
||||
text: qsTr("Copy label/ID")
|
||||
icon: "edit-copy"
|
||||
onClicked: directoryView.copyCurrentItemData("dirName")
|
||||
}
|
||||
PlasmaComponents.MenuItem {
|
||||
text: qsTr("Copy path")
|
||||
icon: "edit-copy"
|
||||
onClicked: directoryView.copyCurrentItemData("dirPath")
|
||||
}
|
||||
PlasmaComponents.MenuItem {
|
||||
separator: true
|
||||
}
|
||||
PlasmaComponents.MenuItem {
|
||||
id: rescanItem
|
||||
text: qsTr('Rescan')
|
||||
text: qsTr("Rescan")
|
||||
icon: "view-refresh"
|
||||
onClicked: directoryView.clickCurrentItemButton(
|
||||
"rescanButton")
|
||||
|
@ -155,7 +170,7 @@ ColumnLayout {
|
|||
}
|
||||
PlasmaComponents.MenuItem {
|
||||
id: openItem
|
||||
text: qsTr('Open in file browser')
|
||||
text: qsTr("Open in file browser")
|
||||
icon: "folder"
|
||||
onClicked: directoryView.clickCurrentItemButton(
|
||||
"openButton")
|
||||
|
|
|
@ -23,6 +23,7 @@ Item {
|
|||
delegate: TopLevelItem {
|
||||
id: item
|
||||
width: downloadView.width
|
||||
readonly property string downloadName: name
|
||||
property alias openButton: openButton
|
||||
|
||||
ColumnLayout {
|
||||
|
@ -134,9 +135,17 @@ Item {
|
|||
PlasmaComponents.Menu {
|
||||
id: contextMenu
|
||||
|
||||
PlasmaComponents.MenuItem {
|
||||
text: qsTr("Copy label/ID")
|
||||
icon: "edit-copy"
|
||||
onClicked: downloadView.copyCurrentItemData("downloadName")
|
||||
}
|
||||
PlasmaComponents.MenuItem {
|
||||
separator: true
|
||||
}
|
||||
PlasmaComponents.MenuItem {
|
||||
id: openItem
|
||||
text: qsTr('Open in file browser')
|
||||
text: qsTr("Open in file browser")
|
||||
icon: "folder"
|
||||
onClicked: downloadView.clickCurrentItemButton("openButton")
|
||||
}
|
||||
|
|
|
@ -33,6 +33,16 @@ ListView {
|
|||
}
|
||||
}
|
||||
|
||||
function copyCurrentItemData(fieldName) {
|
||||
if (!currentItem) {
|
||||
return
|
||||
}
|
||||
var data = currentItem[fieldName]
|
||||
if (data) {
|
||||
plasmoid.nativeInterface.copyToClipboard(data)
|
||||
}
|
||||
}
|
||||
|
||||
function showContextMenu(item, x, y) {
|
||||
if (typeof contextMenu === "undefined") {
|
||||
return
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#include "./devbuttonsitemdelegate.h"
|
||||
#include "./helper.h"
|
||||
|
||||
#include "../../connector/syncthingdev.h"
|
||||
#include "../../model/syncthingdevicemodel.h"
|
||||
|
||||
#include <QClipboard>
|
||||
|
@ -48,59 +49,39 @@ void DevView::mouseReleaseEvent(QMouseEvent *event)
|
|||
|
||||
void DevView::showContextMenu(const QPoint &position)
|
||||
{
|
||||
if (!selectionModel() || selectionModel()->selectedRows(0).size() != 1) {
|
||||
const auto selectedRow = SelectedRow(this);
|
||||
const auto &selectedIndex = selectedRow.index;
|
||||
if (!selectedRow) {
|
||||
return;
|
||||
}
|
||||
QMenu menu(this);
|
||||
if (selectionModel()->selectedRows(0).at(0).parent().isValid()) {
|
||||
if (selectedIndex.parent().isValid()) {
|
||||
connect(menu.addAction(QIcon::fromTheme(QStringLiteral("edit-copy"), QIcon(QStringLiteral(":/icons/hicolor/scalable/actions/edit-copy.svg"))),
|
||||
tr("Copy value")),
|
||||
&QAction::triggered, this, &DevView::copySelectedItem);
|
||||
&QAction::triggered,
|
||||
copyToClipboard(selectedRow.model->data(selectedRow.model->index(selectedIndex.row(), 1, selectedIndex.parent())).toString()));
|
||||
} else {
|
||||
const auto *const dev = selectedRow.data;
|
||||
connect(menu.addAction(QIcon::fromTheme(QStringLiteral("edit-copy"), QIcon(QStringLiteral(":/icons/hicolor/scalable/actions/edit-copy.svg"))),
|
||||
tr("Copy name")),
|
||||
&QAction::triggered, this, &DevView::copySelectedItem);
|
||||
&QAction::triggered, copyToClipboard(dev->displayName()));
|
||||
connect(menu.addAction(QIcon::fromTheme(QStringLiteral("edit-copy"), QIcon(QStringLiteral(":/icons/hicolor/scalable/actions/edit-copy.svg"))),
|
||||
tr("Copy ID")),
|
||||
&QAction::triggered, this, &DevView::copySelectedItemId);
|
||||
&QAction::triggered, copyToClipboard(dev->id));
|
||||
menu.addSeparator();
|
||||
if (dev->paused) {
|
||||
connect(menu.addAction(QIcon::fromTheme(QStringLiteral("media-playback-start"),
|
||||
QIcon(QStringLiteral(":/icons/hicolor/scalable/actions/media-playback-start.svg"))),
|
||||
tr("Resume")),
|
||||
&QAction::triggered, triggerActionForSelectedRow(this, &DevView::pauseResumeDev));
|
||||
} else {
|
||||
connect(menu.addAction(QIcon::fromTheme(QStringLiteral("media-playback-pause"),
|
||||
QIcon(QStringLiteral(":/icons/hicolor/scalable/actions/media-playback-pause.svg"))),
|
||||
tr("Pause")),
|
||||
&QAction::triggered, triggerActionForSelectedRow(this, &DevView::pauseResumeDev));
|
||||
}
|
||||
}
|
||||
showViewMenu(position, *this, menu);
|
||||
}
|
||||
|
||||
void DevView::copySelectedItem()
|
||||
{
|
||||
if (!selectionModel() || selectionModel()->selectedRows(0).size() != 1) {
|
||||
return;
|
||||
}
|
||||
const QModelIndex selectedIndex = selectionModel()->selectedRows(0).at(0);
|
||||
QString text;
|
||||
if (selectedIndex.parent().isValid()) {
|
||||
// dev attribute
|
||||
text = model()->data(model()->index(selectedIndex.row(), 1, selectedIndex.parent())).toString();
|
||||
} else {
|
||||
// dev name/id
|
||||
text = model()->data(selectedIndex).toString();
|
||||
}
|
||||
if (!text.isEmpty()) {
|
||||
QGuiApplication::clipboard()->setText(text);
|
||||
}
|
||||
}
|
||||
|
||||
void DevView::copySelectedItemId()
|
||||
{
|
||||
if (!selectionModel() || selectionModel()->selectedRows(0).size() != 1) {
|
||||
return;
|
||||
}
|
||||
const QModelIndex selectedIndex = selectionModel()->selectedRows(0).at(0);
|
||||
QString text;
|
||||
if (selectedIndex.parent().isValid()) {
|
||||
// dev attribute: should be handled by copySelectedItemId()
|
||||
} else {
|
||||
// dev name/id
|
||||
text = model()->data(model()->index(0, 1, selectedIndex)).toString();
|
||||
}
|
||||
if (!text.isEmpty()) {
|
||||
QGuiApplication::clipboard()->setText(text);
|
||||
}
|
||||
}
|
||||
} // namespace QtGui
|
||||
|
|
|
@ -5,13 +5,16 @@
|
|||
|
||||
namespace Data {
|
||||
struct SyncthingDev;
|
||||
}
|
||||
class SyncthingDeviceModel;
|
||||
} // namespace Data
|
||||
|
||||
namespace QtGui {
|
||||
|
||||
class DevView : public QTreeView {
|
||||
Q_OBJECT
|
||||
public:
|
||||
using ModelType = Data::SyncthingDeviceModel;
|
||||
|
||||
DevView(QWidget *parent = nullptr);
|
||||
|
||||
Q_SIGNALS:
|
||||
|
@ -22,8 +25,6 @@ protected:
|
|||
|
||||
private Q_SLOTS:
|
||||
void showContextMenu(const QPoint &position);
|
||||
void copySelectedItem();
|
||||
void copySelectedItemId();
|
||||
};
|
||||
} // namespace QtGui
|
||||
|
||||
|
|
|
@ -72,59 +72,46 @@ void DirView::mouseReleaseEvent(QMouseEvent *event)
|
|||
|
||||
void DirView::showContextMenu(const QPoint &position)
|
||||
{
|
||||
if (!selectionModel() || selectionModel()->selectedRows(0).size() != 1) {
|
||||
const auto selectedRow = SelectedRow(this);
|
||||
const auto &selectedIndex = selectedRow.index;
|
||||
if (!selectedRow) {
|
||||
return;
|
||||
}
|
||||
QMenu menu(this);
|
||||
if (selectionModel()->selectedRows(0).at(0).parent().isValid()) {
|
||||
if (selectedIndex.parent().isValid()) {
|
||||
connect(menu.addAction(QIcon::fromTheme(QStringLiteral("edit-copy"), QIcon(QStringLiteral(":/icons/hicolor/scalable/actions/edit-copy.svg"))),
|
||||
tr("Copy value")),
|
||||
&QAction::triggered, this, &DirView::copySelectedItem);
|
||||
&QAction::triggered,
|
||||
copyToClipboard(selectedRow.model->data(selectedRow.model->index(selectedIndex.row(), 1, selectedIndex.parent())).toString()));
|
||||
} else {
|
||||
const auto *const dir = selectedRow.data;
|
||||
connect(menu.addAction(QIcon::fromTheme(QStringLiteral("edit-copy"), QIcon(QStringLiteral(":/icons/hicolor/scalable/actions/edit-copy.svg"))),
|
||||
tr("Copy label/ID")),
|
||||
&QAction::triggered, this, &DirView::copySelectedItem);
|
||||
&QAction::triggered, copyToClipboard(dir->displayName()));
|
||||
connect(menu.addAction(QIcon::fromTheme(QStringLiteral("edit-copy"), QIcon(QStringLiteral(":/icons/hicolor/scalable/actions/edit-copy.svg"))),
|
||||
tr("Copy path")),
|
||||
&QAction::triggered, this, &DirView::copySelectedItemPath);
|
||||
&QAction::triggered, copyToClipboard(dir->path));
|
||||
menu.addSeparator();
|
||||
connect(menu.addAction(
|
||||
QIcon::fromTheme(QStringLiteral("view-refresh"), QIcon(QStringLiteral(":/icons/hicolor/scalable/actions/view-refresh.svg"))),
|
||||
tr("Rescan")),
|
||||
&QAction::triggered, triggerActionForSelectedRow(this, &DirView::scanDir));
|
||||
if (dir->paused) {
|
||||
connect(menu.addAction(QIcon::fromTheme(QStringLiteral("media-playback-start"),
|
||||
QIcon(QStringLiteral(":/icons/hicolor/scalable/actions/media-playback-start.svg"))),
|
||||
tr("Resume")),
|
||||
&QAction::triggered, triggerActionForSelectedRow(this, &DirView::pauseResumeDir));
|
||||
} else {
|
||||
connect(menu.addAction(QIcon::fromTheme(QStringLiteral("media-playback-pause"),
|
||||
QIcon(QStringLiteral(":/icons/hicolor/scalable/actions/media-playback-pause.svg"))),
|
||||
tr("Pause")),
|
||||
&QAction::triggered, triggerActionForSelectedRow(this, &DirView::pauseResumeDir));
|
||||
}
|
||||
connect(menu.addAction(QIcon::fromTheme(QStringLiteral("folder"), QIcon(QStringLiteral(":/icons/hicolor/scalable/places/folder-open.svg"))),
|
||||
tr("Open in file browser")),
|
||||
&QAction::triggered, triggerActionForSelectedRow(this, &DirView::openDir));
|
||||
}
|
||||
showViewMenu(position, *this, menu);
|
||||
}
|
||||
|
||||
void DirView::copySelectedItem()
|
||||
{
|
||||
if (!selectionModel() || selectionModel()->selectedRows(0).size() != 1) {
|
||||
return;
|
||||
}
|
||||
const QModelIndex selectedIndex = selectionModel()->selectedRows(0).at(0);
|
||||
QString text;
|
||||
if (selectedIndex.parent().isValid()) {
|
||||
// dev attribute
|
||||
text = model()->data(model()->index(selectedIndex.row(), 1, selectedIndex.parent())).toString();
|
||||
} else {
|
||||
// dev label/id
|
||||
text = model()->data(selectedIndex).toString();
|
||||
}
|
||||
if (!text.isEmpty()) {
|
||||
QGuiApplication::clipboard()->setText(text);
|
||||
}
|
||||
}
|
||||
|
||||
void DirView::copySelectedItemPath()
|
||||
{
|
||||
if (!selectionModel() || selectionModel()->selectedRows(0).size() != 1) {
|
||||
return;
|
||||
}
|
||||
const QModelIndex selectedIndex = selectionModel()->selectedRows(0).at(0);
|
||||
QString text;
|
||||
if (selectedIndex.parent().isValid()) {
|
||||
// dev attribute: should be handled by copySelectedItem() only
|
||||
} else {
|
||||
// dev path
|
||||
text = model()->data(model()->index(1, 1, selectedIndex)).toString();
|
||||
}
|
||||
if (!text.isEmpty()) {
|
||||
QGuiApplication::clipboard()->setText(text);
|
||||
}
|
||||
}
|
||||
} // namespace QtGui
|
||||
|
|
|
@ -5,13 +5,16 @@
|
|||
|
||||
namespace Data {
|
||||
struct SyncthingDir;
|
||||
}
|
||||
class SyncthingDirectoryModel;
|
||||
} // namespace Data
|
||||
|
||||
namespace QtGui {
|
||||
|
||||
class DirView : public QTreeView {
|
||||
Q_OBJECT
|
||||
public:
|
||||
using ModelType = Data::SyncthingDirectoryModel;
|
||||
|
||||
DirView(QWidget *parent = nullptr);
|
||||
|
||||
Q_SIGNALS:
|
||||
|
@ -24,8 +27,6 @@ protected:
|
|||
|
||||
private Q_SLOTS:
|
||||
void showContextMenu(const QPoint &position);
|
||||
void copySelectedItem();
|
||||
void copySelectedItemPath();
|
||||
};
|
||||
} // namespace QtGui
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#include "./downloaditemdelegate.h"
|
||||
#include "./helper.h"
|
||||
|
||||
#include "../../connector/syncthingdir.h"
|
||||
#include "../../model/syncthingdownloadmodel.h"
|
||||
|
||||
#include <QClipboard>
|
||||
|
@ -53,38 +54,36 @@ void DownloadView::mouseReleaseEvent(QMouseEvent *event)
|
|||
|
||||
void DownloadView::showContextMenu(const QPoint &position)
|
||||
{
|
||||
if (!selectionModel() || selectionModel()->selectedRows(0).size() != 1) {
|
||||
const auto selectedRow = SelectedRow(this);
|
||||
const auto &selectedIndex = selectedRow.index;
|
||||
if (!selectedRow) {
|
||||
return;
|
||||
}
|
||||
QMenu menu(this);
|
||||
if (selectionModel()->selectedRows(0).at(0).parent().isValid()) {
|
||||
if (selectedIndex.parent().isValid()) {
|
||||
connect(menu.addAction(QIcon::fromTheme(QStringLiteral("edit-copy"), QIcon(QStringLiteral(":/icons/hicolor/scalable/actions/edit-copy.svg"))),
|
||||
tr("Copy value")),
|
||||
&QAction::triggered, this, &DownloadView::copySelectedItem);
|
||||
&QAction::triggered, copyToClipboard(model()->data(model()->index(selectedIndex.row(), 1, selectedIndex.parent())).toString()));
|
||||
} else {
|
||||
const auto [dir, progress] = selectedRow.data;
|
||||
connect(menu.addAction(QIcon::fromTheme(QStringLiteral("edit-copy"), QIcon(QStringLiteral(":/icons/hicolor/scalable/actions/edit-copy.svg"))),
|
||||
tr("Copy label/ID")),
|
||||
&QAction::triggered, this, &DownloadView::copySelectedItem);
|
||||
&QAction::triggered, copyToClipboard(dir->displayName()));
|
||||
menu.addSeparator();
|
||||
connect(menu.addAction(QIcon::fromTheme(QStringLiteral("folder"), QIcon(QStringLiteral(":/icons/hicolor/scalable/places/folder-open.svg"))),
|
||||
tr("Open in file browser")),
|
||||
&QAction::triggered, triggerActionForSelectedRow(this, &DownloadView::emitOpenDir));
|
||||
}
|
||||
showViewMenu(position, *this, menu);
|
||||
}
|
||||
|
||||
void DownloadView::copySelectedItem()
|
||||
void DownloadView::emitOpenDir(QPair<const SyncthingDir *, const SyncthingItemDownloadProgress *> info)
|
||||
{
|
||||
if (!selectionModel() || selectionModel()->selectedRows(0).size() != 1) {
|
||||
return;
|
||||
}
|
||||
const QModelIndex selectedIndex = selectionModel()->selectedRows(0).at(0);
|
||||
QString text;
|
||||
if (selectedIndex.parent().isValid()) {
|
||||
// dev attribute
|
||||
text = model()->data(model()->index(selectedIndex.row(), 1, selectedIndex.parent())).toString();
|
||||
if (info.second) {
|
||||
emit openItemDir(*info.second);
|
||||
} else {
|
||||
// dev label/id
|
||||
text = model()->data(selectedIndex).toString();
|
||||
}
|
||||
if (!text.isEmpty()) {
|
||||
QGuiApplication::clipboard()->setText(text);
|
||||
emit openDir(*info.first);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace QtGui
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
namespace Data {
|
||||
struct SyncthingItemDownloadProgress;
|
||||
struct SyncthingDir;
|
||||
class SyncthingDownloadModel;
|
||||
} // namespace Data
|
||||
|
||||
namespace QtGui {
|
||||
|
@ -13,6 +14,8 @@ namespace QtGui {
|
|||
class DownloadView : public QTreeView {
|
||||
Q_OBJECT
|
||||
public:
|
||||
using ModelType = Data::SyncthingDownloadModel;
|
||||
|
||||
DownloadView(QWidget *parent = nullptr);
|
||||
|
||||
Q_SIGNALS:
|
||||
|
@ -24,7 +27,9 @@ protected:
|
|||
|
||||
private Q_SLOTS:
|
||||
void showContextMenu(const QPoint &position);
|
||||
void copySelectedItem();
|
||||
|
||||
private:
|
||||
void emitOpenDir(QPair<const Data::SyncthingDir *, const Data::SyncthingItemDownloadProgress *> info);
|
||||
};
|
||||
} // namespace QtGui
|
||||
|
||||
|
|
|
@ -1,16 +1,72 @@
|
|||
#ifndef TRAY_GUI_HELPER_H
|
||||
#define TRAY_GUI_HELPER_H
|
||||
|
||||
#include <QtGlobal>
|
||||
#include <c++utilities/misc/traits.h>
|
||||
|
||||
#include <QClipboard>
|
||||
#include <QGuiApplication>
|
||||
#include <QModelIndex>
|
||||
#include <QTreeView>
|
||||
|
||||
QT_FORWARD_DECLARE_CLASS(QPoint)
|
||||
QT_FORWARD_DECLARE_CLASS(QTreeView)
|
||||
QT_FORWARD_DECLARE_CLASS(QMenu)
|
||||
|
||||
namespace QtGui {
|
||||
|
||||
void showViewMenu(const QPoint &position, const QTreeView &view, QMenu &menu);
|
||||
|
||||
inline auto copyToClipboard(const QString &text)
|
||||
{
|
||||
return [=] { QGuiApplication::clipboard()->setText(text); };
|
||||
}
|
||||
|
||||
template <typename ViewType> struct SelectedRow {
|
||||
explicit SelectedRow(ViewType *view);
|
||||
operator bool() const;
|
||||
|
||||
typename ViewType::ModelType *model = nullptr;
|
||||
QModelIndex index;
|
||||
decltype(model->info(index)) data = decltype(model->info(index))();
|
||||
};
|
||||
|
||||
template <typename ViewType> SelectedRow<ViewType>::SelectedRow(ViewType *view)
|
||||
{
|
||||
auto *const selectionModel = view->selectionModel();
|
||||
if (!selectionModel) {
|
||||
return;
|
||||
}
|
||||
const auto selectedRows = selectionModel->selectedRows(0);
|
||||
if (selectedRows.size() != 1) {
|
||||
return;
|
||||
}
|
||||
index = selectedRows.at(0);
|
||||
model = qobject_cast<typename ViewType::ModelType *>(view->model());
|
||||
if (model) {
|
||||
data = model->info(index);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename ViewType> SelectedRow<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, typename ActionType> inline auto triggerActionForSelectedRow(ViewType *view, ActionType action)
|
||||
{
|
||||
return [=] {
|
||||
if (const auto selectedRow = SelectedRow(view)) {
|
||||
std::invoke(action, view, CppUtilities::Traits::dereferenceMaybe(selectedRow.data));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
} // namespace QtGui
|
||||
|
||||
#endif // TRAY_GUI_HELPER_H
|
||||
|
|
Loading…
Reference in New Issue