Add cut-copy-paste support for streams
This commit is contained in:
parent
fd6f2c2508
commit
43f6959dcc
@ -22,6 +22,10 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
#include "portgrouplist.h"
|
||||
#include "qicon.h"
|
||||
|
||||
#include <QMimeData>
|
||||
|
||||
const QLatin1String kStreamsMimeType("application/vnd.ostinato.streams");
|
||||
|
||||
StreamModel::StreamModel(PortGroupList *p, QObject *parent)
|
||||
: QAbstractTableModel(parent)
|
||||
{
|
||||
@ -223,6 +227,77 @@ QVariant StreamModel::headerData(int section, Qt::Orientation orientation, int r
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
QStringList StreamModel::mimeTypes() const
|
||||
{
|
||||
return QStringList() << kStreamsMimeType;
|
||||
}
|
||||
|
||||
QMimeData* StreamModel::mimeData(const QModelIndexList &indexes) const
|
||||
{
|
||||
using ::google::protobuf::uint8;
|
||||
|
||||
if (indexes.isEmpty())
|
||||
return nullptr;
|
||||
|
||||
// indexes may include multiple columns for a row - but we are only
|
||||
// interested in rows 'coz we have a single data for all columns
|
||||
// XXX: use QMap instead of QSet to keep rows in sorted order
|
||||
QMap<int, int> rows;
|
||||
foreach(QModelIndex index, indexes)
|
||||
rows.insert(index.row(), index.row());
|
||||
|
||||
OstProto::StreamConfigList streams;
|
||||
streams.mutable_port_id()->set_id(mCurrentPort->id());
|
||||
foreach(int row, rows) {
|
||||
OstProto::Stream *stream = streams.add_stream();
|
||||
mCurrentPort->streamByIndex(row)->protoDataCopyInto(*stream);
|
||||
}
|
||||
|
||||
QByteArray data;
|
||||
data.resize(streams.ByteSize());
|
||||
streams.SerializeWithCachedSizesToArray((uint8*)data.data());
|
||||
//qDebug("copy %s", streams.DebugString().c_str());
|
||||
//TODO: copy DebugString as text/plain?
|
||||
|
||||
QMimeData *mimeData = new QMimeData();
|
||||
mimeData->setData(kStreamsMimeType, data);
|
||||
return mimeData; // XXX: caller is expected to take ownership and free!
|
||||
}
|
||||
|
||||
bool StreamModel::dropMimeData(const QMimeData *data, Qt::DropAction action,
|
||||
int row, int /*column*/, const QModelIndex &parent)
|
||||
{
|
||||
if (!data)
|
||||
return false;
|
||||
|
||||
if (!data->hasFormat(kStreamsMimeType))
|
||||
return false;
|
||||
|
||||
if (action != Qt::CopyAction)
|
||||
return false;
|
||||
|
||||
OstProto::StreamConfigList streamsData;
|
||||
QByteArray ba(data->data(kStreamsMimeType));
|
||||
streamsData.ParseFromArray((void*)ba.constData(), ba.size());
|
||||
//qDebug("paste %s", streamsData.DebugString().c_str());
|
||||
|
||||
QList<Stream*> streams;
|
||||
for (int i = 0; i < streamsData.stream_size(); i++) {
|
||||
Stream *stream = new Stream;
|
||||
stream->protoDataCopyFrom(streamsData.stream(i));
|
||||
streams.append(stream);
|
||||
}
|
||||
|
||||
if ((row < 0) || (row > rowCount(parent)))
|
||||
row = rowCount(parent);
|
||||
|
||||
// Delete rows that we are going to overwrite
|
||||
if (row < rowCount(parent))
|
||||
removeRows(row, qMin(rowCount() - row, streams.size()));
|
||||
|
||||
return insert(row, streams); // callee will free streams after insert
|
||||
}
|
||||
|
||||
/*!
|
||||
* Inserts streams before the given row
|
||||
*
|
||||
|
@ -39,12 +39,19 @@ class StreamModel : public QAbstractTableModel
|
||||
|
||||
int rowCount(const QModelIndex &parent = QModelIndex()) const;
|
||||
int columnCount(const QModelIndex &parent = QModelIndex()) const;
|
||||
|
||||
Qt::ItemFlags flags(const QModelIndex &index) const;
|
||||
QVariant data(const QModelIndex &index, int role) const;
|
||||
bool setData(const QModelIndex &index, const QVariant &value,
|
||||
int role = Qt::EditRole);
|
||||
QVariant headerData(int section, Qt::Orientation orientation,
|
||||
int role = Qt::DisplayRole) const;
|
||||
|
||||
QStringList mimeTypes() const;
|
||||
QMimeData* mimeData(const QModelIndexList &indexes) const;
|
||||
bool dropMimeData(const QMimeData *data, Qt::DropAction action,
|
||||
int row, int column, const QModelIndex &parent);
|
||||
|
||||
bool insert(int row, QList<Stream*> &streams);
|
||||
bool insertRows (int row, int count,
|
||||
const QModelIndex & parent = QModelIndex());
|
||||
|
@ -24,6 +24,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
|
||||
#include <QClipboard>
|
||||
#include <QKeyEvent>
|
||||
#include <QMimeData>
|
||||
#include <QPainter>
|
||||
|
||||
class XTableView : public QTableView
|
||||
@ -46,18 +47,76 @@ protected:
|
||||
}
|
||||
|
||||
virtual void keyPressEvent(QKeyEvent *event)
|
||||
{
|
||||
if (event->matches(QKeySequence::Cut)) {
|
||||
cut();
|
||||
} else if (event->matches(QKeySequence::Copy)) {
|
||||
copy();
|
||||
} else if (event->matches(QKeySequence::Paste)) {
|
||||
paste();
|
||||
} else
|
||||
QTableView::keyPressEvent(event);
|
||||
}
|
||||
|
||||
private:
|
||||
void cut()
|
||||
{
|
||||
copy();
|
||||
foreach(QItemSelectionRange range, selectionModel()->selection())
|
||||
model()->removeRows(range.top(), range.height());
|
||||
}
|
||||
|
||||
void copy()
|
||||
{
|
||||
// Copy selection to clipboard (base class copies only current item)
|
||||
// Selection, by default, is in the order in which items were selected
|
||||
// - sort them before copying
|
||||
if (event->matches(QKeySequence::Copy)
|
||||
&& selectionBehavior() == SelectRows) {
|
||||
QModelIndexList selected = selectionModel()->selectedIndexes();
|
||||
std::sort(selected.begin(), selected.end());
|
||||
qApp->clipboard()->setMimeData(model()->mimeData(selected));
|
||||
QModelIndexList selected = selectionModel()->selectedIndexes();
|
||||
|
||||
if (selected.isEmpty())
|
||||
return;
|
||||
|
||||
std::sort(selected.begin(), selected.end());
|
||||
QMimeData *mimeData = model()->mimeData(selected);
|
||||
qApp->clipboard()->setMimeData(mimeData);
|
||||
qDebug("Copied data in %d format(s) to clipboard",
|
||||
mimeData->formats().size());
|
||||
for (int i = 0; i < mimeData->formats().size(); i++) {
|
||||
qDebug(" %d: %s, %d bytes", i+1,
|
||||
qPrintable(mimeData->formats().at(i)),
|
||||
mimeData->data(mimeData->formats().at(i)).size());
|
||||
}
|
||||
else
|
||||
QTableView::keyPressEvent(event);
|
||||
}
|
||||
|
||||
void paste()
|
||||
{
|
||||
const QMimeData *mimeData = qApp->clipboard()->mimeData();
|
||||
|
||||
if (!mimeData)
|
||||
return;
|
||||
|
||||
if (selectionModel()->hasSelection()
|
||||
&& selectionModel()->selection().size() > 1) {
|
||||
qWarning("Cannot paste into multiple(%d) selections",
|
||||
selectionModel()->selection().size());
|
||||
return;
|
||||
}
|
||||
|
||||
// If no selection, insert at the end
|
||||
int row, column;
|
||||
if (selectionModel()->hasSelection()
|
||||
&& selectionModel()->selection().size() == 1) {
|
||||
row = selectionModel()->selection().first().top();
|
||||
column = selectionModel()->selection().first().left();
|
||||
} else {
|
||||
row = model()->rowCount();
|
||||
column = model()->columnCount();
|
||||
}
|
||||
|
||||
if (model()->canDropMimeData(mimeData, Qt::CopyAction,
|
||||
row, column, QModelIndex()))
|
||||
model()->dropMimeData(mimeData, Qt::CopyAction,
|
||||
row, column, QModelIndex());
|
||||
}
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user