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:
Srivats P 2020-03-14 21:13:24 +05:30
parent 4b16c95b2a
commit 18d024481f
12 changed files with 206 additions and 5 deletions

109
client/clipboardhelper.cpp Normal file
View 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
View 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

View File

@ -19,6 +19,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
#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 <http://www.gnu.org/licenses/>
#include <QHeaderView>
#include <QKeyEvent>
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)

BIN
client/icons/copy.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 663 B

BIN
client/icons/cut.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 648 B

BIN
client/icons/paste.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 703 B

View File

@ -23,6 +23,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
#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);

View File

@ -40,6 +40,11 @@
<addaction name="actionHelpAbout" />
<addaction name="actionAboutQt" />
</widget>
<widget class="QMenu" name="menuEdit" >
<property name="title" >
<string>&amp;Edit</string>
</property>
</widget>
<widget class="QMenu" name="menuView" >
<property name="title" >
<string>&amp;View</string>
@ -48,6 +53,7 @@
<addaction name="actionViewRestoreDefaults" />
</widget>
<addaction name="menuFile" />
<addaction name="menuEdit" />
<addaction name="menuView" />
<addaction name="menuHelp" />
</widget>

View File

@ -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 \

View File

@ -14,8 +14,10 @@
<file>icons/bullet_red.png</file>
<file>icons/bullet_white.png</file>
<file>icons/bullet_yellow.png</file>
<file>icons/copy.png</file>
<file>icons/control_play.png</file>
<file>icons/control_stop.png</file>
<file>icons/cut.png</file>
<file>icons/delete.png</file>
<file>icons/devicegroup_add.png</file>
<file>icons/devicegroup_delete.png</file>
@ -35,6 +37,7 @@
<file>icons/name.png</file>
<file>icons/neighbor_clear.png</file>
<file>icons/neighbor_resolve.png</file>
<file>icons/paste.png</file>
<file>icons/portgroup_add.png</file>
<file>icons/portgroup_connect.png</file>
<file>icons/portgroup_delete.png</file>

View File

@ -20,6 +20,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
#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 <http://www.gnu.org/licenses/>
#include <QMessageBox>
#include <QSortFilterProxyModel>
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

View File

@ -22,6 +22,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
#include <QTableView>
#include <QApplication>
#include <QClipboard>
#include <QKeyEvent>
#include <QMimeData>
@ -29,10 +30,19 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
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();