Refactor Clipboard methods (#5627)

* Moves mimeType from StringPairDrag to Clipboard

* Simplifies decodeKey and decodeValue methods

* Adds method to copy a string to clipboard

* Adds method to copy a string pair to the Clipboard

* Adds convenience methods to Clipboard.h to retrieve the QMimeData from the clipboard and checking whether a particular mime type format is present on it

* Uses only the TCOV copy/paste methods on the song editor
To keep consistency on the behavior of the TCOV copy and paste operations, we now only use the TCOV::copy() and TCOV::paste() methods for copying both individual and multiple TCOs.

* Removes obsolete TrackContentObject::cut() and merge copy() and paste() methods to single function TrackContentObject::copyStateTo()

* Adds Clipboard::getString method to get data for particular mime type

* Makes AutomatableModelView.cpp use the Clipboard class instead of calling Qt clipboard directly
This commit is contained in:
IanCaio
2020-10-10 03:17:25 -03:00
committed by GitHub
parent 892aec318d
commit b64fe8e7c0
14 changed files with 212 additions and 200 deletions

View File

@@ -29,25 +29,40 @@
#include <QDomElement>
class JournallingObject;
class Clipboard
namespace Clipboard
{
public:
typedef QMap<QString, QDomElement> Map;
static void copy( JournallingObject * _object );
static const QDomElement * getContent( const QString & _node_name );
static const char * mimeType()
enum class MimeType
{
return( "application/x-lmms-clipboard" );
StringPair,
Default
};
// Convenience Methods
const QMimeData * getMimeData();
bool hasFormat( MimeType mT );
// Helper methods for String data
void copyString( const QString & str, MimeType mT );
QString getString( MimeType mT );
// Helper methods for String Pair data
void copyStringPair( const QString & key, const QString & value );
QString decodeKey( const QMimeData * mimeData );
QString decodeValue( const QMimeData * mimeData );
inline const char * mimeType( MimeType type )
{
switch( type )
{
case MimeType::StringPair:
return "application/x-lmms-stringpair";
break;
case MimeType::Default:
default:
return "application/x-lmms-clipboard";
break;
}
}
private:
static Map content;
} ;
#endif

View File

@@ -45,16 +45,8 @@ public:
static bool processDragEnterEvent( QDragEnterEvent * _dee,
const QString & _allowed_keys );
static QString decodeMimeKey( const QMimeData * mimeData );
static QString decodeMimeValue( const QMimeData * mimeData );
static QString decodeKey( QDropEvent * _de );
static QString decodeValue( QDropEvent * _de );
static const char * mimeType()
{
return( "application/x-lmms-stringpair" );
}
} ;

View File

@@ -155,9 +155,10 @@ public:
MidiTime startTimeOffset() const;
void setStartTimeOffset( const MidiTime &startTimeOffset );
// Will copy the state of a TCO to another TCO
static void copyStateTo( TrackContentObject *src, TrackContentObject *dst );
public slots:
void copy();
void paste();
void toggleMute();
@@ -266,7 +267,6 @@ public:
public slots:
virtual bool close();
void cut();
void remove();
void update() override;

View File

@@ -33,6 +33,7 @@
#include "Lv2SubPluginFeatures.h"
#include "Mixer.h"
#include "StringPairDrag.h"
#include "Clipboard.h"
#include "embed.h"
#include "plugin_export.h"
@@ -238,12 +239,15 @@ Lv2InsView::Lv2InsView(Lv2Instrument *_instrument, QWidget *_parent) :
void Lv2InsView::dragEnterEvent(QDragEnterEvent *_dee)
{
// For mimeType() and MimeType enum class
using namespace Clipboard;
void (QDragEnterEvent::*reaction)(void) = &QDragEnterEvent::ignore;
if (_dee->mimeData()->hasFormat(StringPairDrag::mimeType()))
if (_dee->mimeData()->hasFormat( mimeType( MimeType::StringPair )))
{
const QString txt =
_dee->mimeData()->data(StringPairDrag::mimeType());
_dee->mimeData()->data( mimeType( MimeType::StringPair ) );
if (txt.section(':', 0, 0) == "pluginpresetfile") {
reaction = &QDragEnterEvent::acceptProposedAction;
}

View File

@@ -44,6 +44,7 @@
#include "Song.h"
#include "StringPairDrag.h"
#include "ToolTip.h"
#include "Clipboard.h"
#include "embed.h"
#include "plugin_export.h"
@@ -568,10 +569,13 @@ AudioFileProcessorView::~AudioFileProcessorView()
void AudioFileProcessorView::dragEnterEvent( QDragEnterEvent * _dee )
{
if( _dee->mimeData()->hasFormat( StringPairDrag::mimeType() ) )
// For mimeType() and MimeType enum class
using namespace Clipboard;
if( _dee->mimeData()->hasFormat( mimeType( MimeType::StringPair ) ) )
{
QString txt = _dee->mimeData()->data(
StringPairDrag::mimeType() );
mimeType( MimeType::StringPair ) );
if( txt.section( ':', 0, 0 ) == QString( "tco_%1" ).arg(
Track::SampleTrack ) )
{

View File

@@ -41,6 +41,7 @@
#include "Song.h"
#include "StringPairDrag.h"
#include "ToolTip.h"
#include "Clipboard.h"
#include "embed.h"
@@ -580,10 +581,13 @@ void PatmanView::updateFilename( void )
void PatmanView::dragEnterEvent( QDragEnterEvent * _dee )
{
if( _dee->mimeData()->hasFormat( StringPairDrag::mimeType() ) )
// For mimeType() and MimeType enum class
using namespace Clipboard;
if( _dee->mimeData()->hasFormat( mimeType( MimeType::StringPair ) ) )
{
QString txt = _dee->mimeData()->data(
StringPairDrag::mimeType() );
mimeType( MimeType::StringPair ) );
if( txt.section( ':', 0, 0 ) == "samplefile" )
{
_dee->acceptProposedAction();

View File

@@ -58,6 +58,7 @@
#include "StringPairDrag.h"
#include "TextFloat.h"
#include "ToolTip.h"
#include "Clipboard.h"
#include "embed.h"
@@ -833,10 +834,13 @@ void VestigeInstrumentView::noteOffAll( void )
void VestigeInstrumentView::dragEnterEvent( QDragEnterEvent * _dee )
{
if( _dee->mimeData()->hasFormat( StringPairDrag::mimeType() ) )
// For mimeType() and MimeType enum class
using namespace Clipboard;
if( _dee->mimeData()->hasFormat( mimeType( MimeType::StringPair ) ) )
{
QString txt = _dee->mimeData()->data(
StringPairDrag::mimeType() );
mimeType( MimeType::StringPair ) );
if( txt.section( ':', 0, 0 ) == "vstplugin" )
{
_dee->acceptProposedAction();
@@ -1175,10 +1179,13 @@ void manageVestigeInstrumentView::syncParameterText()
void manageVestigeInstrumentView::dragEnterEvent( QDragEnterEvent * _dee )
{
if( _dee->mimeData()->hasFormat( StringPairDrag::mimeType() ) )
// For mimeType() and MimeType enum class
using namespace Clipboard;
if( _dee->mimeData()->hasFormat( mimeType( MimeType::StringPair ) ) )
{
QString txt = _dee->mimeData()->data(
StringPairDrag::mimeType() );
mimeType( MimeType::StringPair ) );
if( txt.section( ':', 0, 0 ) == "vstplugin" )
{
_dee->acceptProposedAction();

View File

@@ -47,6 +47,7 @@
#include "LocalZynAddSubFx.h"
#include "Mixer.h"
#include "ControllerConnection.h"
#include "Clipboard.h"
#include "embed.h"
#include "plugin_export.h"
@@ -578,10 +579,13 @@ ZynAddSubFxView::~ZynAddSubFxView()
void ZynAddSubFxView::dragEnterEvent( QDragEnterEvent * _dee )
{
if( _dee->mimeData()->hasFormat( StringPairDrag::mimeType() ) )
// For mimeType() and MimeType enum class
using namespace Clipboard;
if( _dee->mimeData()->hasFormat( mimeType( MimeType::StringPair ) ) )
{
QString txt = _dee->mimeData()->data(
StringPairDrag::mimeType() );
mimeType( MimeType::StringPair ) );
if( txt.section( ':', 0, 0 ) == "pluginpresetfile" )
{
_dee->acceptProposedAction();

View File

@@ -24,37 +24,71 @@
#include <QApplication>
#include <QClipboard>
#include <QMimeData>
#include "Clipboard.h"
#include "JournallingObject.h"
Clipboard::Map Clipboard::content;
void Clipboard::copy( JournallingObject * _obj )
namespace Clipboard
{
QDomDocument doc;
QDomElement parent = doc.createElement( "Clipboard" );
_obj->saveState( doc, parent );
content[_obj->nodeName()] = parent.firstChild().toElement();
// Clear the QApplication clipboard, so we don't have any conflicts when LMMS has to
// decide between the QApplication clipboard and the internal clipboard data
QApplication::clipboard()->clear( QClipboard::Clipboard );
}
const QDomElement * Clipboard::getContent( const QString & _node_name )
{
if( content.find( _node_name ) != content.end() )
const QMimeData * getMimeData()
{
return &content[_node_name];
return QApplication::clipboard()->mimeData( QClipboard::Clipboard );
}
bool hasFormat( MimeType mT )
{
return getMimeData()->hasFormat( mimeType( mT ) );
}
void copyString( const QString & str, MimeType mT )
{
QMimeData *content = new QMimeData;
content->setData( mimeType( mT ), str.toUtf8() );
QApplication::clipboard()->setMimeData( content, QClipboard::Clipboard );
}
QString getString( MimeType mT )
{
return QString( getMimeData()->data( mimeType( mT ) ) );
}
void copyStringPair( const QString & key, const QString & value )
{
QString finalString = key + ":" + value;
QMimeData *content = new QMimeData;
content->setData( mimeType( MimeType::StringPair ), finalString.toUtf8() );
QApplication::clipboard()->setMimeData( content, QClipboard::Clipboard );
}
QString decodeKey( const QMimeData * mimeData )
{
return( QString::fromUtf8( mimeData->data( mimeType( MimeType::StringPair ) ) ).section( ':', 0, 0 ) );
}
QString decodeValue( const QMimeData * mimeData )
{
return( QString::fromUtf8( mimeData->data( mimeType( MimeType::StringPair ) ) ).section( ':', 1, -1 ) );
}
return NULL;
}

View File

@@ -184,34 +184,25 @@ bool TrackContentObject::comparePosition(const TrackContentObject *a, const Trac
/*! \brief Copy this TrackContentObject to the clipboard.
/*! \brief Copies the state of a TrackContentObject to another TrackContentObject
*
* Copies this track content object to the clipboard.
* This method copies the state of a TCO to another TCO
*/
void TrackContentObject::copy()
void TrackContentObject::copyStateTo( TrackContentObject *src, TrackContentObject *dst )
{
Clipboard::copy( this );
}
// If the node names match we copy the state
if( src->nodeName() == dst->nodeName() ){
QDomDocument doc;
QDomElement parent = doc.createElement( "StateCopy" );
src->saveState( doc, parent );
const MidiTime pos = dst->startPosition();
dst->restoreState( parent.firstChild().toElement() );
dst->movePosition( pos );
/*! \brief Pastes this TrackContentObject into a track.
*
* Pastes this track content object into a track.
*
* \param _je The journal entry to undo
*/
void TrackContentObject::paste()
{
if( Clipboard::getContent( nodeName() ) != NULL )
{
const MidiTime pos = startPosition();
restoreState( *( Clipboard::getContent( nodeName() ) ) );
movePosition( pos );
AutomationPattern::resolveAllIDs();
GuiApplication::instance()->automationEditor()->m_editor->updateAfterPatternChange();
}
AutomationPattern::resolveAllIDs();
GuiApplication::instance()->automationEditor()->m_editor->updateAfterPatternChange();
}
@@ -478,20 +469,6 @@ void TrackContentObjectView::remove()
/*! \brief Cut this trackContentObjectView from its track to the clipboard.
*
* Perform the 'cut' action of the clipboard - copies the track content
* object to the clipboard and then removes it from the track.
*/
void TrackContentObjectView::cut()
{
m_tco->copy();
remove();
}
/*! \brief Updates a trackContentObjectView's length
*
* If this track content object view has a fixed TCO, then we must
@@ -1239,75 +1216,40 @@ void TrackContentObjectView::remove( QVector<TrackContentObjectView *> tcovs )
void TrackContentObjectView::copy( QVector<TrackContentObjectView *> tcovs )
{
// Checks if there are other selected TCOs and if so copy them as well
if( tcovs.size() > 1 )
{
// Write the TCOs to a DataFile for copying
DataFile dataFile = createTCODataFiles( tcovs );
// For copyStringPair()
using namespace Clipboard;
// Add the TCO type as a key to the final string
QString finalString = QString( "tco_%1:%2" ).arg( m_tco->getTrack()->type() ).arg( dataFile.toString() );
// Write the TCOs to a DataFile for copying
DataFile dataFile = createTCODataFiles( tcovs );
// Copy it to the clipboard
QMimeData *tco_content = new QMimeData;
tco_content->setData( StringPairDrag::mimeType(), finalString.toUtf8() );
QApplication::clipboard()->setMimeData( tco_content, QClipboard::Clipboard );
}
else
{
tcovs.at(0)->getTrackContentObject()->copy();
}
// Copy the TCO type as a key and the TCO data file to the clipboard
copyStringPair( QString( "tco_%1" ).arg( m_tco->getTrack()->type() ),
dataFile.toString() );
}
void TrackContentObjectView::cut( QVector<TrackContentObjectView *> tcovs )
{
// Checks if there are other selected TCOs and if so cut them as well
if( tcovs.size() > 1 )
{
// Write the TCOs to a DataFile for copying
DataFile dataFile = createTCODataFiles( tcovs );
// Copy the selected TCOs
copy( tcovs );
// Now that the dataFile is created we can delete the tracks, since we are cutting
// TODO: Is it safe to call tcov->remove(); on the current TCOV instance?
remove( tcovs );
// Add the TCO type as a key to the final string
QString finalString = QString( "tco_%1:%2" ).arg( m_tco->getTrack()->type() ).arg( dataFile.toString() );
// Copy it to the clipboard
QMimeData *tco_content = new QMimeData;
tco_content->setData( StringPairDrag::mimeType(), finalString.toUtf8() );
QApplication::clipboard()->setMimeData( tco_content, QClipboard::Clipboard );
}
else
{
tcovs.at(0)->cut();
}
// Now that the TCOs are copied we can delete them, since we are cutting
remove( tcovs );
}
void TrackContentObjectView::paste()
{
// NOTE: Because we give preference to the QApplication clipboard over the LMMS Clipboard class, we need to
// clear the QApplication Clipboard during the LMMS Clipboard copy operations (Clipboard::copy does that)
// For getMimeData()
using namespace Clipboard;
// If we have TCO data on the clipboard paste it. If not, do our regular TCO paste.
if( QApplication::clipboard()->mimeData( QClipboard::Clipboard )->hasFormat( StringPairDrag::mimeType() ) )
// If possible, paste the selection on the MidiTime of the selected Track and remove it
MidiTime tcoPos = MidiTime( m_tco->startPosition() );
TrackContentWidget *tcw = getTrackView()->getTrackContentWidget();
if( tcw->pasteSelection( tcoPos, getMimeData() ) )
{
// Paste the selection on the MidiTime of the selected Track
const QMimeData *md = QApplication::clipboard()->mimeData( QClipboard::Clipboard );
MidiTime tcoPos = MidiTime( m_tco->startPosition() );
TrackContentWidget *tcw = getTrackView()->getTrackContentWidget();
if( tcw->pasteSelection( tcoPos, md ) == true )
{
// If we succeed on the paste we delete the TCO we pasted on
remove();
}
}
else
{
getTrackContentObject()->paste();
// If we succeed on the paste we delete the TCO we pasted on
remove();
}
}
@@ -1705,9 +1647,12 @@ bool TrackContentWidget::canPasteSelection( MidiTime tcoPos, const QDropEvent* d
// Overloaded method to make it possible to call this method without a Drag&Drop event
bool TrackContentWidget::canPasteSelection( MidiTime tcoPos, const QMimeData* md , bool allowSameBar )
{
// For decodeKey() and decodeValue()
using namespace Clipboard;
Track * t = getTrack();
QString type = StringPairDrag::decodeMimeKey( md );
QString value = StringPairDrag::decodeMimeValue( md );
QString type = decodeKey( md );
QString value = decodeValue( md );
// We can only paste into tracks of the same type
if( type != ( "tco_" + QString::number( t->type() ) ) ||
@@ -1791,14 +1736,17 @@ bool TrackContentWidget::pasteSelection( MidiTime tcoPos, QDropEvent * de )
// Overloaded method so we can call it without a Drag&Drop event
bool TrackContentWidget::pasteSelection( MidiTime tcoPos, const QMimeData * md, bool skipSafetyCheck )
{
// For decodeKey() and decodeValue()
using namespace Clipboard;
// When canPasteSelection was already called before, skipSafetyCheck will skip this
if( !skipSafetyCheck && canPasteSelection( tcoPos, md ) == false )
{
return false;
}
QString type = StringPairDrag::decodeMimeKey( md );
QString value = StringPairDrag::decodeMimeValue( md );
QString type = decodeKey( md );
QString value = decodeValue( md );
getTrack()->addJournalCheckPoint();
@@ -1985,6 +1933,9 @@ MidiTime TrackContentWidget::endPosition( const MidiTime & posStart )
void TrackContentWidget::contextMenuEvent( QContextMenuEvent * cme )
{
// For hasFormat(), MimeType enum class and getMimeData()
using namespace Clipboard;
if( cme->modifiers() )
{
return;
@@ -1992,8 +1943,7 @@ void TrackContentWidget::contextMenuEvent( QContextMenuEvent * cme )
// If we don't have TCO data in the clipboard there's no need to create this menu
// since "paste" is the only action at the moment.
const QMimeData *md = QApplication::clipboard()->mimeData( QClipboard::Clipboard );
if( !md->hasFormat( StringPairDrag::mimeType() ) )
if( ! hasFormat( MimeType::StringPair ) )
{
return;
}
@@ -2002,21 +1952,23 @@ void TrackContentWidget::contextMenuEvent( QContextMenuEvent * cme )
QAction *pasteA = contextMenu.addAction( embed::getIconPixmap( "edit_paste" ),
tr( "Paste" ), [this, cme](){ contextMenuAction( cme, Paste ); } );
// If we can't paste in the current TCW for some reason, disable the action so the user knows
pasteA->setEnabled( canPasteSelection( getPosition( cme->x() ), md ) ? true : false );
pasteA->setEnabled( canPasteSelection( getPosition( cme->x() ), getMimeData() ) ? true : false );
contextMenu.exec( QCursor::pos() );
}
void TrackContentWidget::contextMenuAction( QContextMenuEvent * cme, ContextMenuAction action )
{
// For getMimeData()
using namespace Clipboard;
switch( action )
{
case Paste:
// Paste the selection on the MidiTime of the context menu event
const QMimeData *md = QApplication::clipboard()->mimeData( QClipboard::Clipboard );
MidiTime tcoPos = getPosition( cme->x() );
pasteSelection( tcoPos, md );
pasteSelection( tcoPos, getMimeData() );
break;
}
}

View File

@@ -23,7 +23,6 @@
*/
#include <QApplication>
#include <QClipboard>
#include <QMenu>
#include <QMouseEvent>
@@ -35,6 +34,7 @@
#include "GuiApplication.h"
#include "MainWindow.h"
#include "StringPairDrag.h"
#include "Clipboard.h"
#include "AutomationEditor.h"
@@ -255,8 +255,10 @@ void AutomatableModelViewSlots::unlinkAllModels()
void AutomatableModelViewSlots::copyToClipboard()
{
QClipboard* clipboard = QApplication::clipboard();
clipboard->setText(QString::number(m_amv->value<float>() * m_amv->getConversionFactor()));
// For copyString() and MimeType enum class
using namespace Clipboard;
copyString( QString::number( m_amv->value<float>() * m_amv->getConversionFactor() ), MimeType::Default );
}
void AutomatableModelViewSlots::pasteFromClipboard()
@@ -272,7 +274,9 @@ void AutomatableModelViewSlots::pasteFromClipboard()
/// Attempt to parse a float from the clipboard
static float floatFromClipboard(bool* ok)
{
const QClipboard* clipboard = QApplication::clipboard();
return clipboard->text().toFloat(ok);
// For getString() and MimeType enum class
using namespace Clipboard;
return getString( MimeType::Default ).toFloat(ok);
}

View File

@@ -32,12 +32,16 @@
#include "StringPairDrag.h"
#include "GuiApplication.h"
#include "MainWindow.h"
#include "Clipboard.h"
StringPairDrag::StringPairDrag( const QString & _key, const QString & _value,
const QPixmap & _icon, QWidget * _w ) :
QDrag( _w )
{
// For mimeType() and MimeType enum class
using namespace Clipboard;
if( _icon.isNull() && _w )
{
setPixmap( _w->grab().scaled(
@@ -51,7 +55,7 @@ StringPairDrag::StringPairDrag( const QString & _key, const QString & _value,
}
QString txt = _key + ":" + _value;
QMimeData * m = new QMimeData();
m->setData( mimeType(), txt.toUtf8() );
m->setData( mimeType( MimeType::StringPair ), txt.toUtf8() );
setMimeData( m );
exec( Qt::LinkAction, Qt::LinkAction );
}
@@ -75,11 +79,14 @@ StringPairDrag::~StringPairDrag()
bool StringPairDrag::processDragEnterEvent( QDragEnterEvent * _dee,
const QString & _allowed_keys )
{
if( !_dee->mimeData()->hasFormat( mimeType() ) )
// For mimeType() and MimeType enum class
using namespace Clipboard;
if( !_dee->mimeData()->hasFormat( mimeType( MimeType::StringPair ) ) )
{
return( false );
}
QString txt = _dee->mimeData()->data( mimeType() );
QString txt = _dee->mimeData()->data( mimeType( MimeType::StringPair ) );
if( _allowed_keys.split( ',' ).contains( txt.section( ':', 0, 0 ) ) )
{
_dee->acceptProposedAction();
@@ -92,25 +99,9 @@ bool StringPairDrag::processDragEnterEvent( QDragEnterEvent * _dee,
QString StringPairDrag::decodeMimeKey( const QMimeData * mimeData )
{
return( QString::fromUtf8( mimeData->data( mimeType() ) ).section( ':', 0, 0 ) );
}
QString StringPairDrag::decodeMimeValue( const QMimeData * mimeData )
{
return( QString::fromUtf8( mimeData->data( mimeType() ) ).section( ':', 1, -1 ) );
}
QString StringPairDrag::decodeKey( QDropEvent * _de )
{
return decodeMimeKey( _de->mimeData() );
return Clipboard::decodeKey( _de->mimeData() );
}
@@ -118,5 +109,5 @@ QString StringPairDrag::decodeKey( QDropEvent * _de )
QString StringPairDrag::decodeValue( QDropEvent * _de )
{
return decodeMimeValue( _de->mimeData() );
return Clipboard::decodeValue( _de->mimeData() );
}

View File

@@ -3901,6 +3901,9 @@ void PianoRoll::updateYScroll()
void PianoRoll::copyToClipboard( const NoteVector & notes ) const
{
// For copyString() and MimeType enum class
using namespace Clipboard;
DataFile dataFile( DataFile::ClipboardData );
QDomElement note_list = dataFile.createElement( "note-list" );
dataFile.content().appendChild( note_list );
@@ -3913,10 +3916,7 @@ void PianoRoll::copyToClipboard( const NoteVector & notes ) const
clip_note.saveState( dataFile, note_list );
}
QMimeData * clip_content = new QMimeData;
clip_content->setData( Clipboard::mimeType(), dataFile.toString().toUtf8() );
QApplication::clipboard()->setMimeData( clip_content,
QClipboard::Clipboard );
copyString( dataFile.toString(), MimeType::Default );
}
@@ -3969,14 +3969,15 @@ void PianoRoll::cutSelectedNotes()
void PianoRoll::pasteNotes()
{
// For getString() and MimeType enum class
using namespace Clipboard;
if( ! hasValidPattern() )
{
return;
}
QString value = QApplication::clipboard()
->mimeData( QClipboard::Clipboard )
->data( Clipboard::mimeType() );
QString value = getString( MimeType::Default );
if( ! value.isEmpty() )
{

View File

@@ -525,8 +525,8 @@ void BBTrack::loadTrackSpecificSettings( const QDomElement & _this )
for( TrackContainer::TrackList::iterator it = tl.begin();
it != tl.end(); ++it )
{
( *it )->getTCO( src )->copy();
( *it )->getTCO( dst )->paste();
TrackContentObject::copyStateTo( ( *it )->getTCO( src ),
( *it )->getTCO( dst ) );
}
setName( tr( "Clone of %1" ).arg(
_this.parentNode().toElement().attribute( "name" ) ) );