Added initial clipboard support.

This commit is contained in:
Jim Evins
2016-04-24 16:52:14 -04:00
parent 4a0fff3f33
commit 6045b9e6b6
8 changed files with 231 additions and 35 deletions
+96
View File
@@ -23,10 +23,21 @@
#include <QFileInfo>
#include <algorithm>
#include <cmath>
#include <QApplication>
#include <QClipboard>
#include <QMimeData>
#include <QtDebug>
#include "LabelModelObject.h"
#include "LabelRegion.h"
#include "XmlLabelCreator.h"
#include "XmlLabelParser.h"
namespace
{
const QString MIME_TYPE = "application/x-glabels-objects";
}
///
@@ -1081,6 +1092,91 @@ void LabelModel::setSelectionFillColorNode( ColorNode fillColorNode )
}
///
/// Copy selection to clipboard
///
void LabelModel::copySelection()
{
if ( !isSelectionEmpty() )
{
QClipboard *clipboard = QApplication::clipboard();
QString buffer;
XmlLabelCreator::serializeObjects( getSelection(), buffer );
QMimeData *mimeData = new QMimeData;
mimeData->setData( MIME_TYPE, buffer.toUtf8() );
clipboard->setMimeData( mimeData );
}
}
///
/// Cut selection to clipboard
///
void LabelModel::cutSelection()
{
copySelection();
deleteSelection();
}
///
/// Can we paste?
///
bool LabelModel::canPaste()
{
const QClipboard *clipboard = QApplication::clipboard();
const QMimeData *mimeData = clipboard->mimeData();
if ( mimeData->hasFormat( MIME_TYPE ) )
{
return true;
}
else if ( mimeData->hasImage() )
{
// TODO: return true
}
else if ( mimeData->hasText() )
{
// TODO: return true
}
return false;
}
///
/// Paste from clipboard
///
void LabelModel::paste()
{
const QClipboard *clipboard = QApplication::clipboard();
const QMimeData *mimeData = clipboard->mimeData();
if ( mimeData->hasFormat( MIME_TYPE ) )
{
QByteArray buffer = mimeData->data( MIME_TYPE );
QList <LabelModelObject*> objects = XmlLabelParser::deserializeObjects( QString(buffer) );
unselectAll();
foreach ( LabelModelObject* object, objects )
{
addObject( object );
selectObject( object );
}
}
else if ( mimeData->hasImage() )
{
// TODO: create an image object from image
}
else if ( mimeData->hasText() )
{
// TODO: create a text object from text
}
}
///
/// Draw label objects
///
+8
View File
@@ -174,6 +174,14 @@ public:
void setSelectionFillColorNode( ColorNode fillColorNode );
/////////////////////////////////
// Clipboard operations
/////////////////////////////////
void copySelection();
void cutSelection();
bool canPaste();
void paste();
/////////////////////////////////
// Drawing operations
/////////////////////////////////
+14 -6
View File
@@ -20,6 +20,7 @@
#include "MainWindow.h"
#include <QClipboard>
#include <QSettings>
#include <QStatusBar>
#include <QFrame>
@@ -125,6 +126,7 @@ MainWindow::MainWindow()
connect( mContents, SIGNAL(currentItemChanged(QListWidgetItem*,QListWidgetItem*)),
this, SLOT(changePage(QListWidgetItem*,QListWidgetItem*)));
connect( mLabelEditor, SIGNAL(zoomChanged()), this, SLOT(onZoomChanged()) );
connect( QApplication::clipboard(), SIGNAL(dataChanged()), this, SLOT(clipboardChanged()) );
#if 0
connect( mLabelEditor, SIGNAL(pointerMoved(double, double)),
this, SLOT(onPointerMoved(double, double)) );
@@ -726,9 +728,6 @@ void MainWindow::setDocVerbsEnabled( bool enabled )
fileSaveAsAction->setEnabled( enabled );
editUndoAction->setEnabled( enabled );
editRedoAction->setEnabled( enabled );
editCutAction->setEnabled( enabled );
editCopyAction->setEnabled( enabled );
editPasteAction->setEnabled( enabled );
editDeleteAction->setEnabled( enabled );
editSelectAllAction->setEnabled( enabled );
editUnSelectAllAction->setEnabled( enabled );
@@ -903,6 +902,15 @@ void MainWindow::changePage(QListWidgetItem *current, QListWidgetItem *previous)
}
///
/// Clipboard contents changed
///
void MainWindow::clipboardChanged()
{
setPasteVerbsEnabled( mModel->canPaste() );
}
///
/// File->New Action
///
@@ -989,7 +997,7 @@ void MainWindow::editRedo()
///
void MainWindow::editCut()
{
qDebug() << "ACTION: edit->Cut";
mModel->cutSelection();
}
@@ -998,7 +1006,7 @@ void MainWindow::editCut()
///
void MainWindow::editCopy()
{
qDebug() << "ACTION: edit->Copy";
mModel->copySelection();
}
@@ -1007,7 +1015,7 @@ void MainWindow::editCopy()
///
void MainWindow::editPaste()
{
qDebug() << "ACTION: edit->Paste";
mModel->paste();
}
+2
View File
@@ -84,6 +84,8 @@ protected:
private slots:
void changePage(QListWidgetItem *current, QListWidgetItem *previous);
void clipboardChanged();
void fileNew();
void fileOpen();
void fileSave();
+28 -3
View File
@@ -65,6 +65,24 @@ XmlLabelCreator::writeBuffer( const LabelModel* label, QString& buffer )
}
void
XmlLabelCreator::serializeObjects( const QList<LabelModelObject*>& objects,
QString& buffer )
{
QDomDocument doc;
QDomNode xmlNode( doc.createProcessingInstruction( "xml", "version=\"1.0\"" ) );
doc.appendChild( xmlNode );
QDomElement root = doc.createElement( "Glabels-objects" );
doc.appendChild( root );
addObjectsToNode( root, objects );
buffer = doc.toString( 2 );
}
void
XmlLabelCreator::createDoc( QDomDocument& doc, const LabelModel* label )
{
@@ -94,16 +112,23 @@ XmlLabelCreator::createObjectsNode( QDomElement &parent, const LabelModel* label
glabels::XmlUtil::setStringAttr( node, "id", "0" );
glabels::XmlUtil::setBoolAttr( node, "rotate", label->rotate() );
foreach ( LabelModelObject* object, label->objectList() )
addObjectsToNode( node, label->objectList() );
}
void
XmlLabelCreator::addObjectsToNode( QDomElement &parent, const QList<LabelModelObject*>& objects )
{
foreach ( LabelModelObject* object, objects )
{
if ( LabelModelBoxObject* boxObject = dynamic_cast<LabelModelBoxObject*>(object) )
{
createObjectBoxNode( node, boxObject );
createObjectBoxNode( parent, boxObject );
}
// TODO: other object types
else
{
Q_ASSERT_X( false, "XmlLabelCreator::createObjectsNode", "Invalid object type." );
Q_ASSERT_X( false, "XmlLabelCreator::addObjectsToNode", "Invalid object type." );
}
}
}
+2
View File
@@ -46,11 +46,13 @@ class XmlLabelCreator : public QObject
public:
static void writeFile( const LabelModel* label, const QString& fileName );
static void writeBuffer( const LabelModel* label, QString& buffer );
static void serializeObjects( const QList<LabelModelObject*>& objects, QString& buffer );
private:
static void createDoc( QDomDocument& doc, const LabelModel* label );
static void createRootNode( const LabelModel* label );
static void createObjectsNode( QDomElement &parent, const LabelModel* label );
static void addObjectsToNode( QDomElement &parent, const QList<LabelModelObject*>& objects );
static void createObjectBoxNode( QDomElement &parent, const LabelModelBoxObject* object );
static void createObjectEllipseNode( QDomElement &parent, const LabelModelEllipseObject* object );
static void createObjectLineNode( QDomElement &parent, const LabelModelLineObject* object );
+73 -20
View File
@@ -115,6 +115,35 @@ XmlLabelParser::readBuffer( const QString& buffer )
}
QList<LabelModelObject*>
XmlLabelParser::deserializeObjects( const QString& buffer )
{
QList<LabelModelObject*> list;
QDomDocument doc;
QString errorString;
int errorLine;
int errorColumn;
if ( !doc.setContent( buffer, false, &errorString, &errorLine, &errorColumn ) )
{
qWarning() << "Error: Parse error at line " << errorLine
<< "column " << errorColumn
<< ": " << errorString;
return list;
}
QDomElement root = doc.documentElement();
if ( root.tagName() != "Glabels-objects" )
{
qWarning() << "Error: Not a Glabels-objects stream";
return list;
}
return parseObjects( root );
}
void
XmlLabelParser::gunzip( const QByteArray& data, QByteArray& result )
{
@@ -219,52 +248,69 @@ XmlLabelParser::parseRootNode( const QDomElement &node )
}
void
XmlLabelParser::parseObjectsNode( const QDomElement &node, LabelModel* label )
QList<LabelModelObject*>
XmlLabelParser::parseObjects( const QDomElement &node )
{
QList<LabelModelObject*> list;
for ( QDomNode child = node.firstChild(); !child.isNull(); child = child.nextSibling() )
{
QString tagName = child.toElement().tagName();
if ( tagName == "Object-box" )
{
parseObjectBoxNode( child.toElement(), label );
list.append( parseObjectBoxNode( child.toElement() ) );
}
#if 0
else if ( tagName == "Object-ellipse" )
{
parseObjectEllipseNode( child.toElement(), label );
list.append( parseObjectEllipseNode( child.toElement() ) );
}
else if ( tagName == "Object-line" )
{
parseObjectLineNode( child.toElement(), label );
list.append( parseObjectLineNode( child.toElement() ) );
}
else if ( tagName == "Object-image" )
{
parseObjectImageNode( child.toElement(), label );
list.append( parseObjectImageNode( child.toElement() ) );
}
else if ( tagName == "Object-barcode" )
{
parseObjectBarcodeNode( child.toElement(), label );
list.append( parseObjectBarcodeNode( child.toElement() ) );
}
else if ( tagName == "Object-text" )
{
parseObjectTextNode( child.toElement(), label );
list.append( parseObjectTextNode( child.toElement() ) );
}
#endif
else if ( !child.isComment() )
{
qWarning() << "Unexpected" << node.tagName() << "child:" << tagName;
}
}
return list;
}
void
XmlLabelParser::parseObjectBoxNode( const QDomElement &node, LabelModel* label )
XmlLabelParser::parseObjectsNode( const QDomElement &node, LabelModel* label )
{
QList<LabelModelObject*> list = parseObjects( node );
foreach ( LabelModelObject* object, list )
{
label->addObject( object );
}
}
LabelModelBoxObject*
XmlLabelParser::parseObjectBoxNode( const QDomElement &node )
{
using namespace glabels;
LabelModelBoxObject* object = new LabelModelBoxObject();
label->addObject( object );
/* position attrs */
@@ -299,36 +345,43 @@ XmlLabelParser::parseObjectBoxNode( const QDomElement &node, LabelModel* label )
/* shadow attrs */
parseShadowAttrs( node, object );
return object;
}
void
XmlLabelParser::parseObjectEllipseNode( const QDomElement &node, LabelModel* label )
LabelModelEllipseObject*
XmlLabelParser::parseObjectEllipseNode( const QDomElement &node )
{
return 0;
}
void
XmlLabelParser::parseObjectLineNode( const QDomElement &node, LabelModel* label )
LabelModelLineObject*
XmlLabelParser::parseObjectLineNode( const QDomElement &node )
{
return 0;
}
void
XmlLabelParser::parseObjectImageNode( const QDomElement &node, LabelModel* label )
LabelModelImageObject*
XmlLabelParser::parseObjectImageNode( const QDomElement &node )
{
return 0;
}
void
XmlLabelParser::parseObjectBarcodeNode( const QDomElement &node, LabelModel* label )
LabelModelBarcodeObject*
XmlLabelParser::parseObjectBarcodeNode( const QDomElement &node )
{
return 0;
}
void
XmlLabelParser::parseObjectTextNode( const QDomElement &node, LabelModel* label )
LabelModelTextObject*
XmlLabelParser::parseObjectTextNode( const QDomElement &node )
{
return 0;
}
+8 -6
View File
@@ -46,17 +46,19 @@ class XmlLabelParser : public QObject
public:
static LabelModel* readFile( const QString& fileName );
static LabelModel* readBuffer( const QString& buffer );
static QList<LabelModelObject*> deserializeObjects( const QString& buffer );
private:
static void gunzip( const QByteArray& gzippedData, QByteArray& data );
static LabelModel* parseRootNode( const QDomElement &node );
static QList<LabelModelObject*> parseObjects( const QDomElement &node );
static void parseObjectsNode( const QDomElement &node, LabelModel* label );
static void parseObjectBoxNode( const QDomElement &node, LabelModel* label );
static void parseObjectEllipseNode( const QDomElement &node, LabelModel* label );
static void parseObjectLineNode( const QDomElement &node, LabelModel* label );
static void parseObjectImageNode( const QDomElement &node, LabelModel* label );
static void parseObjectBarcodeNode( const QDomElement &node, LabelModel* label );
static void parseObjectTextNode( const QDomElement &node, LabelModel* label );
static LabelModelBoxObject* parseObjectBoxNode( const QDomElement &node );
static LabelModelEllipseObject* parseObjectEllipseNode( const QDomElement &node );
static LabelModelLineObject* parseObjectLineNode( const QDomElement &node );
static LabelModelImageObject* parseObjectImageNode( const QDomElement &node );
static LabelModelBarcodeObject* parseObjectBarcodeNode( const QDomElement &node );
static LabelModelTextObject* parseObjectTextNode( const QDomElement &node );
static void parseTopLevelSpanNode( const QDomElement &node, LabelModelTextObject* object );
static void parseAffineAttrs( const QDomElement &node, LabelModelObject* object );
static void parseShadowAttrs( const QDomElement &node, LabelModelObject* object );