Drag n drop (#223)
Added drop interface for image files, images, and text, dragged from other applications. (#153,#223) - Lock aspect ration on new image objects by default - Communicate context menu click location to paste actions
This commit is contained in:
+84
-2
@@ -38,6 +38,7 @@
|
|||||||
#include "model/Markup.h"
|
#include "model/Markup.h"
|
||||||
#include "model/Settings.h"
|
#include "model/Settings.h"
|
||||||
|
|
||||||
|
#include <QMimeData>
|
||||||
#include <QMouseEvent>
|
#include <QMouseEvent>
|
||||||
#include <QtMath>
|
#include <QtMath>
|
||||||
#include <QtDebug>
|
#include <QtDebug>
|
||||||
@@ -105,6 +106,7 @@ namespace glabels
|
|||||||
|
|
||||||
setMouseTracking( true );
|
setMouseTracking( true );
|
||||||
setFocusPolicy(Qt::StrongFocus);
|
setFocusPolicy(Qt::StrongFocus);
|
||||||
|
setAcceptDrops( true );
|
||||||
|
|
||||||
connect( model::Settings::instance(), SIGNAL(changed()), this, SLOT(onSettingsChanged()) );
|
connect( model::Settings::instance(), SIGNAL(changed()), this, SLOT(onSettingsChanged()) );
|
||||||
onSettingsChanged();
|
onSettingsChanged();
|
||||||
@@ -590,7 +592,7 @@ namespace glabels
|
|||||||
//
|
//
|
||||||
if ( mState == IdleState )
|
if ( mState == IdleState )
|
||||||
{
|
{
|
||||||
emit contextMenuActivate();
|
emit contextMenuActivate( model::Point( xWorld, yWorld ) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -621,7 +623,7 @@ namespace glabels
|
|||||||
/*
|
/*
|
||||||
* Emit signal regardless of mode
|
* Emit signal regardless of mode
|
||||||
*/
|
*/
|
||||||
emit pointerMoved( xWorld, yWorld );
|
emit pointerMoved( model::Point( xWorld, yWorld ) );
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -1027,6 +1029,85 @@ namespace glabels
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Handle drag enter event
|
||||||
|
//
|
||||||
|
void LabelEditor::dragEnterEvent( QDragEnterEvent *event )
|
||||||
|
{
|
||||||
|
if ( event->mimeData()->hasUrls() ||
|
||||||
|
event->mimeData()->hasImage() ||
|
||||||
|
event->mimeData()->hasText() )
|
||||||
|
{
|
||||||
|
event->acceptProposedAction();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
event->ignore();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Handle drag move event
|
||||||
|
//
|
||||||
|
void LabelEditor::dragMoveEvent( QDragMoveEvent *event )
|
||||||
|
{
|
||||||
|
if ( event->mimeData()->hasUrls() ||
|
||||||
|
event->mimeData()->hasImage() ||
|
||||||
|
event->mimeData()->hasText() )
|
||||||
|
{
|
||||||
|
event->acceptProposedAction();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
event->ignore();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Handle drop event
|
||||||
|
//
|
||||||
|
void LabelEditor::dropEvent( QDropEvent *event )
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Transform to label coordinates
|
||||||
|
*/
|
||||||
|
QTransform transform;
|
||||||
|
|
||||||
|
transform.scale( mScale, mScale );
|
||||||
|
transform.translate( mX0.pt(), mY0.pt() );
|
||||||
|
|
||||||
|
QPointF pWorld = transform.inverted().map( event->position() );
|
||||||
|
auto xWorld = model::Distance::pt( pWorld.x() );
|
||||||
|
auto yWorld = model::Distance::pt( pWorld.y() );
|
||||||
|
auto p = model::Point( xWorld, yWorld );
|
||||||
|
|
||||||
|
if ( event->mimeData()->hasUrls() )
|
||||||
|
{
|
||||||
|
mUndoRedoModel->checkpoint( tr("Drop") );
|
||||||
|
mModel->pasteAsUrls( event->mimeData(), p );
|
||||||
|
event->acceptProposedAction();
|
||||||
|
}
|
||||||
|
else if ( event->mimeData()->hasImage() )
|
||||||
|
{
|
||||||
|
mUndoRedoModel->checkpoint( tr("Drop") );
|
||||||
|
mModel->pasteAsImage( event->mimeData(), p );
|
||||||
|
event->acceptProposedAction();
|
||||||
|
}
|
||||||
|
else if ( event->mimeData()->hasText() )
|
||||||
|
{
|
||||||
|
mUndoRedoModel->checkpoint( tr("Drop") );
|
||||||
|
mModel->pasteAsText( event->mimeData(), p );
|
||||||
|
event->acceptProposedAction();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
event->ignore();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Draw Background Layer
|
/// Draw Background Layer
|
||||||
///
|
///
|
||||||
@@ -1283,4 +1364,5 @@ namespace glabels
|
|||||||
emit zoomChanged();
|
emit zoomChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
} // namespace glabels
|
} // namespace glabels
|
||||||
|
|||||||
@@ -57,9 +57,9 @@ namespace glabels
|
|||||||
// Signals
|
// Signals
|
||||||
/////////////////////////////////////
|
/////////////////////////////////////
|
||||||
signals:
|
signals:
|
||||||
void contextMenuActivate();
|
void contextMenuActivate( model::Point p );
|
||||||
void zoomChanged();
|
void zoomChanged();
|
||||||
void pointerMoved( const model::Distance& x, const model::Distance& y );
|
void pointerMoved( model::Point p );
|
||||||
void pointerExited();
|
void pointerExited();
|
||||||
void modeChanged();
|
void modeChanged();
|
||||||
|
|
||||||
@@ -126,6 +126,9 @@ namespace glabels
|
|||||||
void leaveEvent( QEvent* event ) override;
|
void leaveEvent( QEvent* event ) override;
|
||||||
void keyPressEvent( QKeyEvent* event ) override;
|
void keyPressEvent( QKeyEvent* event ) override;
|
||||||
void paintEvent( QPaintEvent* event ) override;
|
void paintEvent( QPaintEvent* event ) override;
|
||||||
|
void dragEnterEvent( QDragEnterEvent *event ) override;
|
||||||
|
void dragMoveEvent( QDragMoveEvent *event ) override;
|
||||||
|
void dropEvent( QDropEvent *event ) override;
|
||||||
|
|
||||||
|
|
||||||
/////////////////////////////////////
|
/////////////////////////////////////
|
||||||
|
|||||||
+30
-9
@@ -196,8 +196,8 @@ namespace glabels
|
|||||||
connect( model::Settings::instance(), SIGNAL(changed()), this, SLOT(onSettingsChanged()) );
|
connect( model::Settings::instance(), SIGNAL(changed()), this, SLOT(onSettingsChanged()) );
|
||||||
connect( QApplication::clipboard(), SIGNAL(dataChanged()), this, SLOT(clipboardChanged()) );
|
connect( QApplication::clipboard(), SIGNAL(dataChanged()), this, SLOT(clipboardChanged()) );
|
||||||
#if 0
|
#if 0
|
||||||
connect( mLabelEditor, SIGNAL(pointerMoved(double, double)),
|
connect( mLabelEditor, SIGNAL(pointerMoved(model::Point)),
|
||||||
this, SLOT(onPointerMoved(double, double)) );
|
this, SLOT(onPointerMoved(modelPoint)) );
|
||||||
connect( mLabelEditor, SIGNAL(pointerExited()), this, SLOT(onPointerExit()) );
|
connect( mLabelEditor, SIGNAL(pointerExited()), this, SLOT(onPointerExit()) );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -253,7 +253,7 @@ namespace glabels
|
|||||||
manageActions();
|
manageActions();
|
||||||
setTitle();
|
setTitle();
|
||||||
|
|
||||||
connect( mLabelEditor, SIGNAL(contextMenuActivate()), this, SLOT(onContextMenuActivate()) );
|
connect( mLabelEditor, SIGNAL(contextMenuActivate(model::Point)), this, SLOT(onContextMenuActivate(model::Point)) );
|
||||||
connect( mModel, SIGNAL(nameChanged()), this, SLOT(onNameChanged()) );
|
connect( mModel, SIGNAL(nameChanged()), this, SLOT(onNameChanged()) );
|
||||||
connect( mModel, SIGNAL(modifiedChanged()), this, SLOT(onModifiedChanged()) );
|
connect( mModel, SIGNAL(modifiedChanged()), this, SLOT(onModifiedChanged()) );
|
||||||
connect( mModel, SIGNAL(selectionChanged()), this, SLOT(onSelectionChanged()) );
|
connect( mModel, SIGNAL(selectionChanged()), this, SLOT(onSelectionChanged()) );
|
||||||
@@ -611,7 +611,7 @@ namespace glabels
|
|||||||
contextPasteAction = new QAction( tr("&Paste"), this );
|
contextPasteAction = new QAction( tr("&Paste"), this );
|
||||||
contextPasteAction->setIcon( Icons::EditPaste() );
|
contextPasteAction->setIcon( Icons::EditPaste() );
|
||||||
contextPasteAction->setStatusTip( tr("Paste the clipboard") );
|
contextPasteAction->setStatusTip( tr("Paste the clipboard") );
|
||||||
connect( contextPasteAction, SIGNAL(triggered()), this, SLOT(editPaste()) );
|
connect( contextPasteAction, SIGNAL(triggered()), this, SLOT(editContextPaste()) );
|
||||||
|
|
||||||
contextDeleteAction = new QAction( tr("&Delete"), this );
|
contextDeleteAction = new QAction( tr("&Delete"), this );
|
||||||
contextDeleteAction->setIcon( QIcon::fromTheme( "edit-delete" ) );
|
contextDeleteAction->setIcon( QIcon::fromTheme( "edit-delete" ) );
|
||||||
@@ -1345,7 +1345,21 @@ namespace glabels
|
|||||||
void MainWindow::editPaste()
|
void MainWindow::editPaste()
|
||||||
{
|
{
|
||||||
mUndoRedoModel->checkpoint( tr("Paste") );
|
mUndoRedoModel->checkpoint( tr("Paste") );
|
||||||
mModel->paste();
|
mModel->paste( model::Point() );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Edit->Paste Action (from context menu)
|
||||||
|
///
|
||||||
|
void MainWindow::editContextPaste()
|
||||||
|
{
|
||||||
|
// Extract original context menu click location
|
||||||
|
auto *action = qobject_cast<QAction *>(sender());
|
||||||
|
auto p = action->data().value<model::Point>();
|
||||||
|
|
||||||
|
mUndoRedoModel->checkpoint( tr("Paste") );
|
||||||
|
mModel->paste( p );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1708,8 +1722,13 @@ namespace glabels
|
|||||||
///
|
///
|
||||||
/// Context Menu Activation
|
/// Context Menu Activation
|
||||||
///
|
///
|
||||||
void MainWindow::onContextMenuActivate()
|
void MainWindow::onContextMenuActivate( model::Point p )
|
||||||
{
|
{
|
||||||
|
// Save click location for potential paste action
|
||||||
|
QVariant variant;
|
||||||
|
variant.setValue( p );
|
||||||
|
contextPasteAction->setData( variant );
|
||||||
|
|
||||||
if ( mModel->isSelectionEmpty() )
|
if ( mModel->isSelectionEmpty() )
|
||||||
{
|
{
|
||||||
noSelectionContextMenu->popup( QCursor::pos() );
|
noSelectionContextMenu->popup( QCursor::pos() );
|
||||||
@@ -1736,10 +1755,12 @@ namespace glabels
|
|||||||
///
|
///
|
||||||
/// Pointer moved: update Cursor Information in Status Bar
|
/// Pointer moved: update Cursor Information in Status Bar
|
||||||
///
|
///
|
||||||
void MainWindow::onPointerMoved( double x, double y )
|
void MainWindow::onPointerMoved( model::Point p )
|
||||||
{
|
{
|
||||||
/* TODO: convert x,y to locale units and set precision accordingly. */
|
/* TODO: set precision accordingly. */
|
||||||
cursorInfoLabel->setText( QString( "%1, %2" ).arg(x).arg(y) );
|
auto units = model::Settings::units();
|
||||||
|
cursorInfoLabel->setText( QString( "%1, %2" ).arg( p.x().toString(units) )
|
||||||
|
.arg( p.y().toString(units) ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -109,6 +109,7 @@ namespace glabels
|
|||||||
void editCut();
|
void editCut();
|
||||||
void editCopy();
|
void editCopy();
|
||||||
void editPaste();
|
void editPaste();
|
||||||
|
void editContextPaste();
|
||||||
void editDelete();
|
void editDelete();
|
||||||
void editSelectAll();
|
void editSelectAll();
|
||||||
void editUnSelectAll();
|
void editUnSelectAll();
|
||||||
@@ -150,10 +151,10 @@ namespace glabels
|
|||||||
void helpReportBug();
|
void helpReportBug();
|
||||||
void helpAbout();
|
void helpAbout();
|
||||||
|
|
||||||
void onContextMenuActivate();
|
void onContextMenuActivate( model::Point );
|
||||||
|
|
||||||
void onZoomChanged();
|
void onZoomChanged();
|
||||||
void onPointerMoved( double, double );
|
void onPointerMoved( model::Point );
|
||||||
void onPointerExit();
|
void onPointerExit();
|
||||||
|
|
||||||
void onNameChanged();
|
void onNameChanged();
|
||||||
|
|||||||
+101
-39
@@ -33,7 +33,6 @@
|
|||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
#include <QClipboard>
|
#include <QClipboard>
|
||||||
#include <QFileInfo>
|
#include <QFileInfo>
|
||||||
#include <QMimeData>
|
|
||||||
#include <QtDebug>
|
#include <QtDebug>
|
||||||
|
|
||||||
|
|
||||||
@@ -1480,67 +1479,130 @@ namespace glabels
|
|||||||
const QClipboard *clipboard = QApplication::clipboard();
|
const QClipboard *clipboard = QApplication::clipboard();
|
||||||
const QMimeData *mimeData = clipboard->mimeData();
|
const QMimeData *mimeData = clipboard->mimeData();
|
||||||
|
|
||||||
if ( mimeData->hasFormat( MIME_TYPE ) )
|
return mimeData->hasFormat( MIME_TYPE ) ||
|
||||||
{
|
mimeData->hasUrls() ||
|
||||||
return true;
|
mimeData->hasImage() ||
|
||||||
}
|
mimeData->hasText();
|
||||||
else if ( mimeData->hasImage() )
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else if ( mimeData->hasText() )
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Paste from clipboard
|
/// Paste from clipboard
|
||||||
///
|
///
|
||||||
void Model::paste()
|
void Model::paste( Point p )
|
||||||
{
|
{
|
||||||
const QClipboard *clipboard = QApplication::clipboard();
|
const QClipboard *clipboard = QApplication::clipboard();
|
||||||
const QMimeData *mimeData = clipboard->mimeData();
|
const QMimeData *mimeData = clipboard->mimeData();
|
||||||
|
|
||||||
if ( mimeData->hasFormat( MIME_TYPE ) )
|
if ( mimeData->hasFormat( MIME_TYPE ) )
|
||||||
{
|
{
|
||||||
// Native objects
|
pasteAsNativeObjects( mimeData, p );
|
||||||
QByteArray buffer = mimeData->data( MIME_TYPE );
|
}
|
||||||
QList <ModelObject*> objects = XmlLabelParser::deserializeObjects( buffer, this );
|
else if ( mimeData->hasUrls() )
|
||||||
|
{
|
||||||
unselectAll();
|
pasteAsUrls( mimeData, p );
|
||||||
foreach ( ModelObject* object, objects )
|
|
||||||
{
|
|
||||||
addObject( object );
|
|
||||||
selectObject( object );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if ( mimeData->hasImage() )
|
else if ( mimeData->hasImage() )
|
||||||
{
|
{
|
||||||
// Create object from clipboard image
|
pasteAsImage( mimeData, p );
|
||||||
auto* object = new ModelImageObject();
|
|
||||||
object->setImage( qvariant_cast<QImage>(mimeData->imageData()) );
|
|
||||||
object->setSize( object->naturalSize() );
|
|
||||||
object->setPosition( (w()-object->w())/2.0, (h()-object->h())/2.0 );
|
|
||||||
addObject( object );
|
|
||||||
unselectAll();
|
|
||||||
selectObject( object );
|
|
||||||
}
|
}
|
||||||
else if ( mimeData->hasText() )
|
else if ( mimeData->hasText() )
|
||||||
{
|
{
|
||||||
// Create object from clipboard text
|
pasteAsText( mimeData, p );
|
||||||
auto* object = new ModelTextObject();
|
}
|
||||||
object->setText( mimeData->text() );
|
}
|
||||||
object->setSize( object->naturalSize() );
|
|
||||||
object->setPosition( (w()-object->w())/2.0, (h()-object->h())/2.0 );
|
|
||||||
|
///
|
||||||
|
/// Paste as native objects
|
||||||
|
///
|
||||||
|
void Model::pasteAsNativeObjects( const QMimeData* mimeData, Point p )
|
||||||
|
{
|
||||||
|
QByteArray buffer = mimeData->data( MIME_TYPE );
|
||||||
|
QList <ModelObject*> objects = XmlLabelParser::deserializeObjects( buffer, this );
|
||||||
|
|
||||||
|
unselectAll();
|
||||||
|
foreach ( ModelObject* object, objects )
|
||||||
|
{
|
||||||
|
object->setPositionRelative( p.x(), p.y() );
|
||||||
addObject( object );
|
addObject( object );
|
||||||
unselectAll();
|
|
||||||
selectObject( object );
|
selectObject( object );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Paste as URLs ( currently only supports local image files )
|
||||||
|
///
|
||||||
|
void Model::pasteAsUrls( const QMimeData* mimeData, Point p )
|
||||||
|
{
|
||||||
|
auto x = p.x();
|
||||||
|
auto y = p.y();
|
||||||
|
auto xOffset = Distance::pt( 10 );
|
||||||
|
auto yOffset = Distance::pt( 10 );
|
||||||
|
|
||||||
|
unselectAll();
|
||||||
|
for ( auto url : mimeData->urls() )
|
||||||
|
{
|
||||||
|
if ( url.isLocalFile() )
|
||||||
|
{
|
||||||
|
auto name = url.toLocalFile();
|
||||||
|
QImage image( name );
|
||||||
|
if ( !image.isNull() )
|
||||||
|
{
|
||||||
|
auto* object = new ModelImageObject();
|
||||||
|
object->setImage( name, image );
|
||||||
|
object->setSize( object->naturalSize() );
|
||||||
|
object->setPosition( x, y );
|
||||||
|
addObject( object );
|
||||||
|
selectObject( object );
|
||||||
|
|
||||||
|
x = fmod( x + xOffset, w() );
|
||||||
|
y = fmod( y + yOffset, h() );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
qWarning() << "Cannot paste" << name
|
||||||
|
<< ": does not exist or currently unsupported file type.";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
qWarning() << "Cannot paste" << url.toString()
|
||||||
|
<< ": currently unsupported file location.";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Paste as image
|
||||||
|
///
|
||||||
|
void Model::pasteAsImage( const QMimeData* mimeData, Point p )
|
||||||
|
{
|
||||||
|
auto* object = new ModelImageObject();
|
||||||
|
object->setImage( qvariant_cast<QImage>(mimeData->imageData()) );
|
||||||
|
object->setSize( object->naturalSize() );
|
||||||
|
object->setPosition( p.x(), p.y() );
|
||||||
|
addObject( object );
|
||||||
|
unselectAll();
|
||||||
|
selectObject( object );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Paste as text
|
||||||
|
void Model::pasteAsText( const QMimeData* mimeData, Point p )
|
||||||
|
{
|
||||||
|
auto* object = new ModelTextObject();
|
||||||
|
object->setText( mimeData->text() );
|
||||||
|
object->setSize( object->naturalSize() );
|
||||||
|
object->setPosition( p.x(), p.y() );
|
||||||
|
addObject( object );
|
||||||
|
unselectAll();
|
||||||
|
selectObject( object );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Draw label objects
|
/// Draw label objects
|
||||||
|
|||||||
+7
-2
@@ -31,6 +31,7 @@
|
|||||||
|
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
#include <QList>
|
#include <QList>
|
||||||
|
#include <QMimeData>
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QPainter>
|
#include <QPainter>
|
||||||
|
|
||||||
@@ -207,8 +208,12 @@ namespace glabels
|
|||||||
void copySelection();
|
void copySelection();
|
||||||
void cutSelection();
|
void cutSelection();
|
||||||
bool canPaste();
|
bool canPaste();
|
||||||
void paste();
|
void paste( Point p );
|
||||||
|
void pasteAsNativeObjects( const QMimeData* mimeData, Point p );
|
||||||
|
void pasteAsUrls( const QMimeData* mimeData, Point p );
|
||||||
|
void pasteAsImage( const QMimeData* mimeData, Point p );
|
||||||
|
void pasteAsText( const QMimeData* mimeData, Point p );
|
||||||
|
|
||||||
/////////////////////////////////
|
/////////////////////////////////
|
||||||
// Drawing operations
|
// Drawing operations
|
||||||
/////////////////////////////////
|
/////////////////////////////////
|
||||||
|
|||||||
@@ -73,6 +73,8 @@ namespace glabels
|
|||||||
{
|
{
|
||||||
smDefaultImage = new QImage( ":images/checkerboard.png" );
|
smDefaultImage = new QImage( ":images/checkerboard.png" );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mLockAspectRatio = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -24,6 +24,8 @@
|
|||||||
|
|
||||||
#include "Distance.h"
|
#include "Distance.h"
|
||||||
|
|
||||||
|
#include <QMetaType>
|
||||||
|
|
||||||
|
|
||||||
namespace glabels
|
namespace glabels
|
||||||
{
|
{
|
||||||
@@ -52,4 +54,7 @@ namespace glabels
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Q_DECLARE_METATYPE( glabels::model::Point )
|
||||||
|
|
||||||
|
|
||||||
#endif // model_Point_h
|
#endif // model_Point_h
|
||||||
|
|||||||
@@ -1328,6 +1328,10 @@
|
|||||||
<source>Resize</source>
|
<source>Resize</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Drop</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
<name>glabels::MainWindow</name>
|
<name>glabels::MainWindow</name>
|
||||||
|
|||||||
Reference in New Issue
Block a user