Add cut-copy-paste to Edit menu and context-menu
Actions have been added to context-menu for stream list and device group list only for now.
This commit is contained in:
parent
4b16c95b2a
commit
18d024481f
109
client/clipboardhelper.cpp
Normal file
109
client/clipboardhelper.cpp
Normal file
@ -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 <http://www.gnu.org/licenses/>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "clipboardhelper.h"
|
||||||
|
|
||||||
|
#include <QAction>
|
||||||
|
#include <QApplication>
|
||||||
|
#include <QClipboard>
|
||||||
|
#include <QIcon>
|
||||||
|
|
||||||
|
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<QAction*> ClipboardHelper::actions()
|
||||||
|
{
|
||||||
|
QList<QAction*> 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));
|
||||||
|
}
|
||||||
|
|
45
client/clipboardhelper.h
Normal file
45
client/clipboardhelper.h
Normal file
@ -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 <http://www.gnu.org/licenses/>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _CLIPBOARD_HELPER_H
|
||||||
|
#define _CLIPBOARD_HELPER_H
|
||||||
|
|
||||||
|
#include <QList>
|
||||||
|
|
||||||
|
class QAction;
|
||||||
|
|
||||||
|
class ClipboardHelper : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
ClipboardHelper(QObject *parent=nullptr);
|
||||||
|
|
||||||
|
QList<QAction*> actions();
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void actionTriggered();
|
||||||
|
void updateActionStatus();
|
||||||
|
|
||||||
|
private:
|
||||||
|
QAction *actionCut_{nullptr};
|
||||||
|
QAction *actionCopy_{nullptr};
|
||||||
|
QAction *actionPaste_{nullptr};
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
@ -19,6 +19,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
|
|||||||
|
|
||||||
#include "deviceswidget.h"
|
#include "deviceswidget.h"
|
||||||
|
|
||||||
|
#include "clipboardhelper.h"
|
||||||
#include "devicegroupdialog.h"
|
#include "devicegroupdialog.h"
|
||||||
#include "port.h"
|
#include "port.h"
|
||||||
#include "portgrouplist.h"
|
#include "portgrouplist.h"
|
||||||
@ -26,6 +27,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
|
|||||||
#include <QHeaderView>
|
#include <QHeaderView>
|
||||||
#include <QKeyEvent>
|
#include <QKeyEvent>
|
||||||
|
|
||||||
|
extern ClipboardHelper *clipboardHelper;
|
||||||
|
|
||||||
DevicesWidget::DevicesWidget(QWidget *parent)
|
DevicesWidget::DevicesWidget(QWidget *parent)
|
||||||
: QWidget(parent), portGroups_(NULL)
|
: QWidget(parent), portGroups_(NULL)
|
||||||
{
|
{
|
||||||
@ -49,6 +52,14 @@ DevicesWidget::DevicesWidget(QWidget *parent)
|
|||||||
|
|
||||||
// DevicesWidget's actions is an aggegate of all sub-widget's actions
|
// DevicesWidget's actions is an aggegate of all sub-widget's actions
|
||||||
addActions(deviceGroupList->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)
|
void DevicesWidget::setPortGroupList(PortGroupList *portGroups)
|
||||||
|
BIN
client/icons/copy.png
Normal file
BIN
client/icons/copy.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 663 B |
BIN
client/icons/cut.png
Normal file
BIN
client/icons/cut.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 648 B |
BIN
client/icons/paste.png
Normal file
BIN
client/icons/paste.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 703 B |
@ -23,6 +23,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
|
|||||||
#include "dbgthread.h"
|
#include "dbgthread.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "clipboardhelper.h"
|
||||||
#include "jumpurl.h"
|
#include "jumpurl.h"
|
||||||
#include "logsmodel.h"
|
#include "logsmodel.h"
|
||||||
#include "logswindow.h"
|
#include "logswindow.h"
|
||||||
@ -60,6 +61,7 @@ extern const char* revision;
|
|||||||
|
|
||||||
PortGroupList *pgl;
|
PortGroupList *pgl;
|
||||||
LogsModel *appLogs;
|
LogsModel *appLogs;
|
||||||
|
ClipboardHelper *clipboardHelper;
|
||||||
|
|
||||||
MainWindow::MainWindow(QWidget *parent)
|
MainWindow::MainWindow(QWidget *parent)
|
||||||
: QMainWindow (parent)
|
: QMainWindow (parent)
|
||||||
@ -94,6 +96,7 @@ MainWindow::MainWindow(QWidget *parent)
|
|||||||
|
|
||||||
pgl = new PortGroupList;
|
pgl = new PortGroupList;
|
||||||
appLogs = new LogsModel(this);
|
appLogs = new LogsModel(this);
|
||||||
|
clipboardHelper = new ClipboardHelper(this);
|
||||||
|
|
||||||
portsWindow = new PortsWindow(pgl, this);
|
portsWindow = new PortsWindow(pgl, this);
|
||||||
statsWindow = new PortStatsWindow(pgl, this);
|
statsWindow = new PortStatsWindow(pgl, this);
|
||||||
@ -117,6 +120,7 @@ MainWindow::MainWindow(QWidget *parent)
|
|||||||
setupUi(this);
|
setupUi(this);
|
||||||
|
|
||||||
menuFile->insertActions(menuFile->actions().at(3), portsWindow->actions());
|
menuFile->insertActions(menuFile->actions().at(3), portsWindow->actions());
|
||||||
|
menuEdit->addActions(clipboardHelper->actions());
|
||||||
|
|
||||||
statsDock->setWidget(statsWindow);
|
statsDock->setWidget(statsWindow);
|
||||||
addDockWidget(Qt::BottomDockWidgetArea, statsDock);
|
addDockWidget(Qt::BottomDockWidgetArea, statsDock);
|
||||||
|
@ -40,6 +40,11 @@
|
|||||||
<addaction name="actionHelpAbout" />
|
<addaction name="actionHelpAbout" />
|
||||||
<addaction name="actionAboutQt" />
|
<addaction name="actionAboutQt" />
|
||||||
</widget>
|
</widget>
|
||||||
|
<widget class="QMenu" name="menuEdit" >
|
||||||
|
<property name="title" >
|
||||||
|
<string>&Edit</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
<widget class="QMenu" name="menuView" >
|
<widget class="QMenu" name="menuView" >
|
||||||
<property name="title" >
|
<property name="title" >
|
||||||
<string>&View</string>
|
<string>&View</string>
|
||||||
@ -48,6 +53,7 @@
|
|||||||
<addaction name="actionViewRestoreDefaults" />
|
<addaction name="actionViewRestoreDefaults" />
|
||||||
</widget>
|
</widget>
|
||||||
<addaction name="menuFile" />
|
<addaction name="menuFile" />
|
||||||
|
<addaction name="menuEdit" />
|
||||||
<addaction name="menuView" />
|
<addaction name="menuView" />
|
||||||
<addaction name="menuHelp" />
|
<addaction name="menuHelp" />
|
||||||
</widget>
|
</widget>
|
||||||
|
@ -35,6 +35,7 @@ LIBS += -L"../extra/qhexedit2/$(OBJECTS_DIR)/" -lqhexedit2
|
|||||||
RESOURCES += ostinato.qrc
|
RESOURCES += ostinato.qrc
|
||||||
HEADERS += \
|
HEADERS += \
|
||||||
arpstatusmodel.h \
|
arpstatusmodel.h \
|
||||||
|
clipboardhelper.h \
|
||||||
devicegroupdialog.h \
|
devicegroupdialog.h \
|
||||||
devicegroupmodel.h \
|
devicegroupmodel.h \
|
||||||
devicemodel.h \
|
devicemodel.h \
|
||||||
@ -64,7 +65,8 @@ HEADERS += \
|
|||||||
streamstatsfiltermodel.h \
|
streamstatsfiltermodel.h \
|
||||||
streamstatsmodel.h \
|
streamstatsmodel.h \
|
||||||
streamstatswindow.h \
|
streamstatswindow.h \
|
||||||
variablefieldswidget.h
|
variablefieldswidget.h \
|
||||||
|
xtableview.h
|
||||||
|
|
||||||
FORMS += \
|
FORMS += \
|
||||||
about.ui \
|
about.ui \
|
||||||
@ -83,6 +85,7 @@ FORMS += \
|
|||||||
|
|
||||||
SOURCES += \
|
SOURCES += \
|
||||||
arpstatusmodel.cpp \
|
arpstatusmodel.cpp \
|
||||||
|
clipboardhelper.cpp \
|
||||||
devicegroupdialog.cpp \
|
devicegroupdialog.cpp \
|
||||||
devicegroupmodel.cpp \
|
devicegroupmodel.cpp \
|
||||||
devicemodel.cpp \
|
devicemodel.cpp \
|
||||||
|
@ -14,8 +14,10 @@
|
|||||||
<file>icons/bullet_red.png</file>
|
<file>icons/bullet_red.png</file>
|
||||||
<file>icons/bullet_white.png</file>
|
<file>icons/bullet_white.png</file>
|
||||||
<file>icons/bullet_yellow.png</file>
|
<file>icons/bullet_yellow.png</file>
|
||||||
|
<file>icons/copy.png</file>
|
||||||
<file>icons/control_play.png</file>
|
<file>icons/control_play.png</file>
|
||||||
<file>icons/control_stop.png</file>
|
<file>icons/control_stop.png</file>
|
||||||
|
<file>icons/cut.png</file>
|
||||||
<file>icons/delete.png</file>
|
<file>icons/delete.png</file>
|
||||||
<file>icons/devicegroup_add.png</file>
|
<file>icons/devicegroup_add.png</file>
|
||||||
<file>icons/devicegroup_delete.png</file>
|
<file>icons/devicegroup_delete.png</file>
|
||||||
@ -35,6 +37,7 @@
|
|||||||
<file>icons/name.png</file>
|
<file>icons/name.png</file>
|
||||||
<file>icons/neighbor_clear.png</file>
|
<file>icons/neighbor_clear.png</file>
|
||||||
<file>icons/neighbor_resolve.png</file>
|
<file>icons/neighbor_resolve.png</file>
|
||||||
|
<file>icons/paste.png</file>
|
||||||
<file>icons/portgroup_add.png</file>
|
<file>icons/portgroup_add.png</file>
|
||||||
<file>icons/portgroup_connect.png</file>
|
<file>icons/portgroup_connect.png</file>
|
||||||
<file>icons/portgroup_delete.png</file>
|
<file>icons/portgroup_delete.png</file>
|
||||||
|
@ -20,6 +20,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
|
|||||||
#include "portswindow.h"
|
#include "portswindow.h"
|
||||||
|
|
||||||
#include "applymsg.h"
|
#include "applymsg.h"
|
||||||
|
#include "clipboardhelper.h"
|
||||||
#include "deviceswidget.h"
|
#include "deviceswidget.h"
|
||||||
#include "portconfigdialog.h"
|
#include "portconfigdialog.h"
|
||||||
#include "settings.h"
|
#include "settings.h"
|
||||||
@ -38,6 +39,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
|
|||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
#include <QSortFilterProxyModel>
|
#include <QSortFilterProxyModel>
|
||||||
|
|
||||||
|
extern ClipboardHelper *clipboardHelper;
|
||||||
extern QMainWindow *mainWindow;
|
extern QMainWindow *mainWindow;
|
||||||
|
|
||||||
PortsWindow::PortsWindow(PortGroupList *pgl, QWidget *parent)
|
PortsWindow::PortsWindow(PortGroupList *pgl, QWidget *parent)
|
||||||
@ -78,9 +80,9 @@ PortsWindow::PortsWindow(PortGroupList *pgl, QWidget *parent)
|
|||||||
tvStreamList->addAction(actionDuplicate_Stream);
|
tvStreamList->addAction(actionDuplicate_Stream);
|
||||||
tvStreamList->addAction(actionDelete_Stream);
|
tvStreamList->addAction(actionDelete_Stream);
|
||||||
|
|
||||||
sep = new QAction(this);
|
QAction *sep2 = new QAction(this);
|
||||||
sep->setSeparator(true);
|
sep2->setSeparator(true);
|
||||||
tvStreamList->addAction(sep);
|
tvStreamList->addAction(sep2);
|
||||||
|
|
||||||
tvStreamList->addAction(actionOpen_Streams);
|
tvStreamList->addAction(actionOpen_Streams);
|
||||||
tvStreamList->addAction(actionSave_Streams);
|
tvStreamList->addAction(actionSave_Streams);
|
||||||
@ -97,6 +99,14 @@ PortsWindow::PortsWindow(PortGroupList *pgl, QWidget *parent)
|
|||||||
addAction(sep);
|
addAction(sep);
|
||||||
addActions(devicesWidget->actions());
|
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());
|
tvStreamList->setModel(plm->getStreamModel());
|
||||||
|
|
||||||
// XXX: It would be ideal if we only needed to do the below to
|
// XXX: It would be ideal if we only needed to do the below to
|
||||||
|
@ -22,6 +22,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
|
|||||||
|
|
||||||
#include <QTableView>
|
#include <QTableView>
|
||||||
|
|
||||||
|
#include <QApplication>
|
||||||
#include <QClipboard>
|
#include <QClipboard>
|
||||||
#include <QKeyEvent>
|
#include <QKeyEvent>
|
||||||
#include <QMimeData>
|
#include <QMimeData>
|
||||||
@ -29,10 +30,19 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
|
|||||||
|
|
||||||
class XTableView : public QTableView
|
class XTableView : public QTableView
|
||||||
{
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
XTableView(QWidget *parent) : QTableView(parent) {}
|
XTableView(QWidget *parent) : QTableView(parent) {}
|
||||||
virtual ~XTableView() {}
|
virtual ~XTableView() {}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
Q_INVOKABLE bool hasSelection() const
|
||||||
|
{
|
||||||
|
return !selectionModel()->selectedIndexes().isEmpty();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void paintEvent(QPaintEvent *event)
|
virtual void paintEvent(QPaintEvent *event)
|
||||||
{
|
{
|
||||||
@ -58,7 +68,7 @@ protected:
|
|||||||
QTableView::keyPressEvent(event);
|
QTableView::keyPressEvent(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
public slots:
|
||||||
void cut()
|
void cut()
|
||||||
{
|
{
|
||||||
copy();
|
copy();
|
||||||
|
Loading…
Reference in New Issue
Block a user