Added initial clipboard support.
This commit is contained in:
@@ -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
|
||||
///
|
||||
|
||||
@@ -174,6 +174,14 @@ public:
|
||||
void setSelectionFillColorNode( ColorNode fillColorNode );
|
||||
|
||||
|
||||
/////////////////////////////////
|
||||
// Clipboard operations
|
||||
/////////////////////////////////
|
||||
void copySelection();
|
||||
void cutSelection();
|
||||
bool canPaste();
|
||||
void paste();
|
||||
|
||||
/////////////////////////////////
|
||||
// Drawing operations
|
||||
/////////////////////////////////
|
||||
|
||||
+14
-6
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -84,6 +84,8 @@ protected:
|
||||
private slots:
|
||||
void changePage(QListWidgetItem *current, QListWidgetItem *previous);
|
||||
|
||||
void clipboardChanged();
|
||||
|
||||
void fileNew();
|
||||
void fileOpen();
|
||||
void fileSave();
|
||||
|
||||
@@ -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." );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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 );
|
||||
|
||||
Reference in New Issue
Block a user