diff --git a/client/clipboardhelper.cpp b/client/clipboardhelper.cpp
new file mode 100644
index 0000000..cbaf62f
--- /dev/null
+++ b/client/clipboardhelper.cpp
@@ -0,0 +1,109 @@
+/*
+Copyright (C) 2020 Srivats P.
+
+This file is part of "Ostinato"
+
+This is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, 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 General Public License
+along with this program. If not, see
+*/
+
+#include "clipboardhelper.h"
+
+#include
+#include
+#include
+#include
+
+ClipboardHelper::ClipboardHelper(QObject *parent)
+ : QObject(parent)
+{
+ actionCut_ = new QAction(tr("&Cut"), this);
+ actionCut_->setObjectName(QStringLiteral("actionCut"));
+ actionCut_->setIcon(QIcon(QString::fromUtf8(":/icons/cut.png")));
+
+ actionCopy_ = new QAction(tr("Cop&y"), this);
+ actionCopy_->setObjectName(QStringLiteral("actionCopy"));
+ actionCopy_->setIcon(QIcon(QString::fromUtf8(":/icons/copy.png")));
+
+ actionPaste_ = new QAction(tr("&Paste"), this);
+ actionPaste_->setObjectName(QStringLiteral("actionPaste"));
+ actionPaste_->setIcon(QIcon(QString::fromUtf8(":/icons/paste.png")));
+
+ connect(actionCut_, SIGNAL(triggered()), SLOT(actionTriggered()));
+ connect(actionCopy_, SIGNAL(triggered()), SLOT(actionTriggered()));
+ connect(actionPaste_, SIGNAL(triggered()), SLOT(actionTriggered()));
+
+#if 0 // FIXME: doesn't work correctly yet
+ connect(qGuiApp, SIGNAL(focusChanged(QWidget*, QWidget*)),
+ SLOT(updateClipboardActions()));
+#endif
+}
+
+QList ClipboardHelper::actions()
+{
+ QList actionList({actionCut_, actionCopy_, actionPaste_});
+ return actionList;
+}
+
+void ClipboardHelper::actionTriggered()
+{
+ QWidget *focusWidget = QApplication::focusWidget();
+
+ if (!focusWidget)
+ return;
+
+ // single slot to handle cut/copy/paste - find which action was triggered
+ QString action = sender()->objectName()
+ .remove("action").append("()").toLower();
+ if (focusWidget->metaObject()->indexOfSlot(qPrintable(action)) < 0) {
+ qDebug("%s slot not found for object %s:%s ",
+ qPrintable(action),
+ qPrintable(focusWidget->objectName()),
+ focusWidget->metaObject()->className());
+ return;
+ }
+
+ action.remove("()");
+ QMetaObject::invokeMethod(focusWidget, qPrintable(action),
+ Qt::DirectConnection);
+}
+
+void ClipboardHelper::updateActionStatus()
+{
+ QWidget *focusWidget = QApplication::focusWidget();
+ if (!focusWidget)
+ return;
+
+ qDebug("In %s", __FUNCTION__);
+
+ const QMetaObject *meta = focusWidget->metaObject();
+ // FIXME: we should check if the mimeData's mimeType can be pasted in
+ // the focusWidget
+ actionPaste_->setEnabled(qGuiApp->clipboard()->mimeData()
+ && (meta->indexOfSlot("paste()") >= 0));
+
+ bool hasSelection = false;
+ if (meta->indexOfProperty("hasSelectedText") >= 0)
+ hasSelection |= focusWidget->property("hasSelectedText").toBool();
+
+ bool ret = false;
+ if (meta->indexOfMethod("hasSelection()") >= 0) {
+ if (QMetaObject::invokeMethod(focusWidget, "hasSelection",
+ Qt::DirectConnection, Q_RETURN_ARG(bool, ret)))
+ hasSelection |= ret;
+ }
+
+ actionCut_->setEnabled(hasSelection && (meta->indexOfSlot("cut") >= 0));
+ actionCopy_->setEnabled(hasSelection && (meta->indexOfSlot("copy") >= 0));
+}
+
diff --git a/client/clipboardhelper.h b/client/clipboardhelper.h
new file mode 100644
index 0000000..9d70382
--- /dev/null
+++ b/client/clipboardhelper.h
@@ -0,0 +1,45 @@
+/*
+Copyright (C) 2020 Srivats P.
+
+This file is part of "Ostinato"
+
+This is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, 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 General Public License
+along with this program. If not, see
+*/
+
+#ifndef _CLIPBOARD_HELPER_H
+#define _CLIPBOARD_HELPER_H
+
+#include
+
+class QAction;
+
+class ClipboardHelper : public QObject
+{
+ Q_OBJECT
+public:
+ ClipboardHelper(QObject *parent=nullptr);
+
+ QList actions();
+
+private slots:
+ void actionTriggered();
+ void updateActionStatus();
+
+private:
+ QAction *actionCut_{nullptr};
+ QAction *actionCopy_{nullptr};
+ QAction *actionPaste_{nullptr};
+};
+
+#endif
diff --git a/client/deviceswidget.cpp b/client/deviceswidget.cpp
index 1a4b303..124bdeb 100644
--- a/client/deviceswidget.cpp
+++ b/client/deviceswidget.cpp
@@ -19,6 +19,7 @@ along with this program. If not, see
#include "deviceswidget.h"
+#include "clipboardhelper.h"
#include "devicegroupdialog.h"
#include "port.h"
#include "portgrouplist.h"
@@ -26,6 +27,8 @@ along with this program. If not, see
#include
#include
+extern ClipboardHelper *clipboardHelper;
+
DevicesWidget::DevicesWidget(QWidget *parent)
: QWidget(parent), portGroups_(NULL)
{
@@ -49,6 +52,14 @@ DevicesWidget::DevicesWidget(QWidget *parent)
// DevicesWidget's actions is an aggegate of all sub-widget's actions
addActions(deviceGroupList->actions());
+
+ // Add the clipboard actions to the context menu of deviceGroupList
+ // but not to DeviceWidget's actions since they are already available
+ // in the global Edit Menu
+ QAction *sep = new QAction("Clipboard", this);
+ sep->setSeparator(true);
+ deviceGroupList->addAction(sep);
+ deviceGroupList->addActions(clipboardHelper->actions());
}
void DevicesWidget::setPortGroupList(PortGroupList *portGroups)
diff --git a/client/icons/copy.png b/client/icons/copy.png
new file mode 100644
index 0000000..195dc6d
Binary files /dev/null and b/client/icons/copy.png differ
diff --git a/client/icons/cut.png b/client/icons/cut.png
new file mode 100644
index 0000000..f215d6f
Binary files /dev/null and b/client/icons/cut.png differ
diff --git a/client/icons/paste.png b/client/icons/paste.png
new file mode 100644
index 0000000..968f073
Binary files /dev/null and b/client/icons/paste.png differ
diff --git a/client/mainwindow.cpp b/client/mainwindow.cpp
index 8ad83c3..7579c1d 100644
--- a/client/mainwindow.cpp
+++ b/client/mainwindow.cpp
@@ -23,6 +23,7 @@ along with this program. If not, see
#include "dbgthread.h"
#endif
+#include "clipboardhelper.h"
#include "jumpurl.h"
#include "logsmodel.h"
#include "logswindow.h"
@@ -60,6 +61,7 @@ extern const char* revision;
PortGroupList *pgl;
LogsModel *appLogs;
+ClipboardHelper *clipboardHelper;
MainWindow::MainWindow(QWidget *parent)
: QMainWindow (parent)
@@ -94,6 +96,7 @@ MainWindow::MainWindow(QWidget *parent)
pgl = new PortGroupList;
appLogs = new LogsModel(this);
+ clipboardHelper = new ClipboardHelper(this);
portsWindow = new PortsWindow(pgl, this);
statsWindow = new PortStatsWindow(pgl, this);
@@ -117,6 +120,7 @@ MainWindow::MainWindow(QWidget *parent)
setupUi(this);
menuFile->insertActions(menuFile->actions().at(3), portsWindow->actions());
+ menuEdit->addActions(clipboardHelper->actions());
statsDock->setWidget(statsWindow);
addDockWidget(Qt::BottomDockWidgetArea, statsDock);
diff --git a/client/mainwindow.ui b/client/mainwindow.ui
index e4cbe55..a01a331 100644
--- a/client/mainwindow.ui
+++ b/client/mainwindow.ui
@@ -40,6 +40,11 @@
+
+
diff --git a/client/ostinato.pro b/client/ostinato.pro
index 77aaa44..d7c6eb6 100644
--- a/client/ostinato.pro
+++ b/client/ostinato.pro
@@ -35,6 +35,7 @@ LIBS += -L"../extra/qhexedit2/$(OBJECTS_DIR)/" -lqhexedit2
RESOURCES += ostinato.qrc
HEADERS += \
arpstatusmodel.h \
+ clipboardhelper.h \
devicegroupdialog.h \
devicegroupmodel.h \
devicemodel.h \
@@ -64,7 +65,8 @@ HEADERS += \
streamstatsfiltermodel.h \
streamstatsmodel.h \
streamstatswindow.h \
- variablefieldswidget.h
+ variablefieldswidget.h \
+ xtableview.h
FORMS += \
about.ui \
@@ -83,6 +85,7 @@ FORMS += \
SOURCES += \
arpstatusmodel.cpp \
+ clipboardhelper.cpp \
devicegroupdialog.cpp \
devicegroupmodel.cpp \
devicemodel.cpp \
diff --git a/client/ostinato.qrc b/client/ostinato.qrc
index e734848..bf35a72 100644
--- a/client/ostinato.qrc
+++ b/client/ostinato.qrc
@@ -14,8 +14,10 @@
icons/bullet_red.png
icons/bullet_white.png
icons/bullet_yellow.png
+ icons/copy.png
icons/control_play.png
icons/control_stop.png
+ icons/cut.png
icons/delete.png
icons/devicegroup_add.png
icons/devicegroup_delete.png
@@ -35,6 +37,7 @@
icons/name.png
icons/neighbor_clear.png
icons/neighbor_resolve.png
+ icons/paste.png
icons/portgroup_add.png
icons/portgroup_connect.png
icons/portgroup_delete.png
diff --git a/client/portswindow.cpp b/client/portswindow.cpp
index a45fda2..cce7678 100644
--- a/client/portswindow.cpp
+++ b/client/portswindow.cpp
@@ -20,6 +20,7 @@ along with this program. If not, see
#include "portswindow.h"
#include "applymsg.h"
+#include "clipboardhelper.h"
#include "deviceswidget.h"
#include "portconfigdialog.h"
#include "settings.h"
@@ -38,6 +39,7 @@ along with this program. If not, see
#include
#include
+extern ClipboardHelper *clipboardHelper;
extern QMainWindow *mainWindow;
PortsWindow::PortsWindow(PortGroupList *pgl, QWidget *parent)
@@ -78,9 +80,9 @@ PortsWindow::PortsWindow(PortGroupList *pgl, QWidget *parent)
tvStreamList->addAction(actionDuplicate_Stream);
tvStreamList->addAction(actionDelete_Stream);
- sep = new QAction(this);
- sep->setSeparator(true);
- tvStreamList->addAction(sep);
+ QAction *sep2 = new QAction(this);
+ sep2->setSeparator(true);
+ tvStreamList->addAction(sep2);
tvStreamList->addAction(actionOpen_Streams);
tvStreamList->addAction(actionSave_Streams);
@@ -97,6 +99,14 @@ PortsWindow::PortsWindow(PortGroupList *pgl, QWidget *parent)
addAction(sep);
addActions(devicesWidget->actions());
+ // Add the clipboard actions to the context menu of streamList
+ // but not to PortsWindow's actions since they are already available
+ // in the global Edit Menu
+ sep = new QAction("Clipboard", this);
+ sep->setSeparator(true);
+ tvStreamList->insertAction(sep2, sep);
+ tvStreamList->insertActions(sep2, clipboardHelper->actions());
+
tvStreamList->setModel(plm->getStreamModel());
// XXX: It would be ideal if we only needed to do the below to
diff --git a/client/xtableview.h b/client/xtableview.h
index 222e399..0f17496 100644
--- a/client/xtableview.h
+++ b/client/xtableview.h
@@ -22,6 +22,7 @@ along with this program. If not, see
#include
+#include
#include
#include
#include
@@ -29,10 +30,19 @@ along with this program. If not, see
class XTableView : public QTableView
{
+ Q_OBJECT
+
public:
XTableView(QWidget *parent) : QTableView(parent) {}
virtual ~XTableView() {}
+#if 0
+ Q_INVOKABLE bool hasSelection() const
+ {
+ return !selectionModel()->selectedIndexes().isEmpty();
+ }
+#endif
+
protected:
virtual void paintEvent(QPaintEvent *event)
{
@@ -58,7 +68,7 @@ protected:
QTableView::keyPressEvent(event);
}
-private:
+public slots:
void cut()
{
copy();