Intial version of new song-editor, more of a viewer right now

git-svn-id: https://lmms.svn.sf.net/svnroot/lmms/trunk/lmms@2013 0778d3d1-df1d-0410-868b-ea421aaaa00d
This commit is contained in:
Paul Giblock
2009-02-11 00:56:03 +00:00
parent a48b0b6ce0
commit f057a52ab9
12 changed files with 756 additions and 2 deletions

View File

@@ -493,7 +493,7 @@ void trackContentObjectView::dropEvent( QDropEvent * _de )
// the user doesn't expect...
midiTime pos = m_tco->startPosition();
m_tco->restoreState( mmp.content().firstChild().toElement() );
m_tco->movePosition( pos );
m_tco->movePosition( pos );
automationPattern::resolveAllIDs();
_de->accept();
}
@@ -1776,6 +1776,7 @@ void track::removeTCO( trackContentObject * _tco )
if( it != m_trackContentObjects.end() )
{
m_trackContentObjects.erase( it );
emit trackContentObjectRemoved( _tco );
engine::getSong()->setModified();
}
}

View File

@@ -170,6 +170,7 @@ void trackContainer::removeTrack( track * _track )
m_tracksMutex.lockForWrite();
m_tracks.remove( index );
m_tracksMutex.unlock();
emit trackRemoved( _track );
if( engine::getSong() )
{
@@ -193,6 +194,7 @@ void trackContainer::clearAllTracks( void )
//m_tracksMutex.lockForWrite();
while( !m_tracks.isEmpty() )
{
emit trackRemoved( m_tracks.first() );
delete m_tracks.first();
}
//m_tracksMutex.unlock();

View File

@@ -40,6 +40,8 @@
#include <QtGui/QRadioButton>
#include <QShortcut>
#include <QGraphicsView>
#include "lmmsversion.h"
#include "main_window.h"
@@ -74,6 +76,7 @@
#include "cpuload_widget.h"
#include "visualization_widget.h"
#include "gui/tracks/track_container_scene.h"
mainWindow::mainWindow( void ) :
@@ -192,6 +195,29 @@ mainWindow::mainWindow( void ) :
vbox->addWidget( w );
setCentralWidget( main_widget );
/// HACK TO CREATE EXTRA SONG EDITOR FOR NOW ///
//Fun test
TrackContainerScene * scene = new TrackContainerScene( this, engine::getSong() );
// Mem leak
QPixmap * sceneBg = new QPixmap( 16*4*2, 32 );
QPainter * sceneBgPainter = new QPainter( sceneBg );
engine::getLmmsStyle()->drawTrackContentBackground(
sceneBgPainter,
QSize( 16*4, 32 ),
16 );
QGraphicsView *view = new QGraphicsView( scene );
view->setRenderHints( QPainter::Antialiasing | QPainter::SmoothPixmapTransform );
view->setDragMode( QGraphicsView::RubberBandDrag );
view->setAlignment( Qt::AlignLeft | Qt::AlignTop );
view->setBackgroundBrush( QBrush(*sceneBg) );
view->show();
//view->scale(2.0, 1.0);
QMdiSubWindow * subWin = workspace()->addSubWindow( view );
/// END HACK TO CREATE EXTRA SONG EDITOR FOR NOW ///
m_updateTimer.start( 1000 / 20, this ); // 20 fps
}

View File

@@ -0,0 +1,118 @@
#include <QGraphicsScene>
#include <QKeyEvent>
#include <QTimeLine>
#include <stdio.h>
#include "gui/tracks/track_container_scene.h"
#include "gui/tracks/track_content_object_item.h"
#include "gui/tracks/track_item.h"
#include "track_container.h"
TrackContainerScene::TrackContainerScene( QObject * parent, trackContainer * _tc ) :
QGraphicsScene( parent ),
//modelView( NULL, this ),
//journallingObject(),
//serializingObjectHook(),
m_trackContainer( _tc ),
m_ppt( 16 )
{
connect( m_trackContainer, SIGNAL( trackAdded( track * ) ),
this, SLOT( addTrack( track * ) ),
Qt::QueuedConnection );
connect( m_trackContainer, SIGNAL( trackRemoved( track * ) ),
this, SLOT( removeTrack( track * ) ) );
}
TrackContainerScene::~TrackContainerScene()
{
}
void TrackContainerScene::setPixelsPerTact( float _ppt )
{
m_ppt = _ppt;
}
void TrackContainerScene::addTrack( track * _t )
{
TrackItem * item = new TrackItem( this, _t );
item->setHeight( DEFAULT_CELL_HEIGHT );
item->setY( m_trackItems.size() * DEFAULT_CELL_HEIGHT );
m_trackItems.insert( _t, item );
}
void TrackContainerScene::removeTrack( track * _t )
{
QMap<track*, TrackItem*>::iterator i =
m_trackItems.find( _t );
if( i != m_trackItems.end() && i.key() == _t )
{
TrackItem * item = i.value();
qreal h = item->height();
i = m_trackItems.erase(i);
delete item;
// Now move everything after back up
while( i != m_trackItems.end() )
{
(*i)->setY( (*i)->y() - h );
++i;
}
}
}
void TrackContainerScene::keyPressEvent( QKeyEvent * event )
{
if( event->modifiers() == Qt::ShiftModifier )
{
const qreal cellWidth = TrackContainerScene::DEFAULT_CELL_WIDTH;
if( event->key() == Qt::Key_Left )
{
}
else if( event->key() == Qt::Key_Right )
{
QTimeLine * timeLine = new QTimeLine();
// TODO: Cleanup the friendly references
QList<QGraphicsItem*> selItems = selectedItems();
for( QList<QGraphicsItem *>::iterator it = selItems.begin();
it != selItems.end(); ++it )
{
TrackContentObjectItem * tcoItem =
dynamic_cast<TrackContentObjectItem*>( *it );
if( tcoItem )
{
qreal destPos = tcoItem->m_snapBackAnimation->posAt( 1.0 ).x();
tcoItem->prepareSnapBackAnimation( timeLine, destPos + cellWidth );
}
}
timeLine->setCurrentTime( 0.0f );
timeLine->setDuration( 300 );
timeLine->setCurveShape( QTimeLine::EaseInOutCurve );
connect( timeLine, SIGNAL(finished()), timeLine, SLOT(deleteLater()));
timeLine->start();
}
}
}
#include "gui/tracks/moc_track_container_scene.cxx"

View File

@@ -0,0 +1,244 @@
#include <QObject>
#include <QGraphicsItem>
#include <QTimeLine>
#include <QGraphicsItemAnimation>
#include <QStyleOptionGraphicsItem>
#include "gui/tracks/track_content_object_item.h"
#include "gui/tracks/track_container_scene.h"
#include "gui/tracks/track_item.h"
#include "track.h"
//QTimeLine TrackContentObjectItem::s_timeLine;
//QGraphicsItemAnimation TrackContentObjectItem::s_animation;
QTimeLine TrackContentObjectItem::s_snapBackTimeLine;
TrackContentObjectItem::TrackContentObjectItem( TrackItem * _track, trackContentObject * _object ) :
QObject(),
QGraphicsItem(),
m_trackItem( _track ),
m_tco( _object ),
m_snapBackAnimation( NULL )
{
//m_object = _object;
setFlags( QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable );
setCursor( Qt::OpenHandCursor );
midiTime startPos = _object->startPosition();
float x = TrackContainerScene::DEFAULT_CELL_WIDTH *
startPos.getTicks() / midiTime::ticksPerTact();
setPos( x, _track->y() );
setZValue(x);
m_snapBackAnimation = new QGraphicsItemAnimation();
m_snapBackAnimation->setItem( this );
}
QRectF TrackContentObjectItem::boundingRect() const
{
qreal penWidth = 1;
// TODO: Calculate based on track length and an adjustable height.
/*return QRectF( -64 - penWidth / 2, -16 - penWidth / 2,
128 + penWidth / 2, 32 + penWidth / 2 );*/
QRectF rc = QRectF( 0, 0, TrackContainerScene::DEFAULT_CELL_WIDTH *
m_tco->length().getTicks() / midiTime::ticksPerTact(), m_trackItem->height() );
return rc;
}
qreal TrackContentObjectItem::zValue() const
{
//return x();
//return m_tco->startPotion().getTicks();
return QGraphicsItem::zValue();
}
void TrackContentObjectItem::updateGeometry()
{
prepareGeometryChange();
}
void TrackContentObjectItem::paint( QPainter * _painter,
const QStyleOptionGraphicsItem * _option, QWidget * _widget )
{
QColor col;
if( !isSelected() )
{
col = QColor( 0x00, 0x33, 0x99 );
}
else
{
col = QColor( 0x99, 0x33, 0x00 );
}
QColor col0 = col.light( 130 );
QColor col1 = col.light( 70 );
QColor col2 = col.light( 40 );
QRectF rc = boundingRect();
qreal xscale = _option->matrix.m11();
_painter->save();
_painter->scale( 1.0f/xscale, 1.0f );
rc.setWidth( rc.width() * xscale );
QLinearGradient lingrad( 0, 0, 0, rc.height() );
lingrad.setColorAt( 0, col0 );
lingrad.setColorAt( 1, col1 );
QLinearGradient bordergrad( 0, 0, 0, rc.height() );
bordergrad.setColorAt( 1, col2 );
bordergrad.setColorAt( 0, col1 );
rc.adjust( 0, 0, -1, -1 );
_painter->setRenderHint( QPainter::Antialiasing, true );
_painter->setBrush( lingrad );
_painter->setPen( QPen( bordergrad, 1.5 ) ); // QColor( 6, 6, 6 ) );
_painter->drawRoundedRect( rc, 4, 4 );
_painter->setRenderHint( QPainter::Antialiasing, false );
_painter->restore();
}
QVariant TrackContentObjectItem::itemChange( GraphicsItemChange _change, const QVariant & _value )
{
if( _change == ItemPositionChange && scene( ) )
{
// value is the new position
QPointF newPos = _value.toPointF( );
//printf("TCO %lld: itemChange (%.2f %.2f) -> ", m_tco, newPos.x(), newPos.y());
if( newPos.x() < 0 )
{
newPos.setX( 0 );
}
if( newPos.y() < 0 )
{
newPos.setY( 0 );
}
/* Let's just short-circuit the Y for now
if( fmod( newPos.y(), 32 ) != 16 )
{
newPos.setY( newPos.y() + 16 - ( fmod( newPos.y(), 32 ) ) );
} */
newPos.setY( m_trackItem->y() );
/*
if( fmod( newPos.x(), 16 ) != 0 )
{
newPos.setX( newPos.x() - ( fmod( newPos.x(), 16 ) ) );
}
if( newPos.x() != x() ) {
setZValue(newPos.x());
}*/
//printf("(%.2f %.2f)\n", newPos.x(), newPos.y());
return newPos;
}
else if( _change == QGraphicsItem::ItemSelectedChange && scene() )
{
bool sel = _value.toBool();
if( sel )
{
setCursor( Qt::OpenHandCursor );
}
else
{
setCursor( Qt::OpenHandCursor );
}
}
return QGraphicsItem::itemChange( _change, _value );
}
void TrackContentObjectItem::mousePressEvent( QGraphicsSceneMouseEvent * event )
{
QGraphicsItem::mousePressEvent( event );
if( isSelected() )
{
setCursor( Qt::ClosedHandCursor );
}
}
void TrackContentObjectItem::mouseReleaseEvent( QGraphicsSceneMouseEvent * event )
{
QGraphicsItem::mouseReleaseEvent( event );
setCursor( Qt::OpenHandCursor );
QTimeLine * timeLine = new QTimeLine();
prepareSnapBackAnimation( timeLine );
if( isSelected() ) {
QList<QGraphicsItem*> selItems = scene()->selectedItems();
for( QList<QGraphicsItem *>::iterator it = selItems.begin();
it != selItems.end(); ++it )
{
TrackContentObjectItem * tcoItem =
dynamic_cast<TrackContentObjectItem*>( *it );
if( tcoItem )
{
tcoItem->prepareSnapBackAnimation( timeLine );
}
}
}
timeLine->setCurrentTime( 0.0f );
timeLine->setDuration( 300 );
timeLine->setCurveShape( QTimeLine::EaseInOutCurve );
connect( timeLine, SIGNAL(finished()), timeLine, SLOT(deleteLater()));
timeLine->start();
}
void TrackContentObjectItem::hoverEnterEvent( QGraphicsSceneHoverEvent * event )
{
QGraphicsItem::hoverEnterEvent( event );
}
void TrackContentObjectItem::hoverLeaveEvent( QGraphicsSceneHoverEvent * event )
{
QGraphicsItem::hoverLeaveEvent( event );
}
void TrackContentObjectItem::prepareSnapBackAnimation( QTimeLine * timeLine )
{
prepareSnapBackAnimation( timeLine, x() );
}
void TrackContentObjectItem::prepareSnapBackAnimation( QTimeLine * timeLine, int newX )
{
const qreal cellWidth = TrackContainerScene::DEFAULT_CELL_WIDTH;
const qreal xVal = newX + TrackContainerScene::DEFAULT_CELL_WIDTH * 0.5f;
QPointF newPos( xVal - ( fmod( xVal, cellWidth) ), y() );
m_snapBackAnimation->setTimeLine( timeLine );
m_snapBackAnimation->setPosAt( 0.0, pos() );
m_snapBackAnimation->setPosAt( 1.0, newPos );
}
#include "gui/tracks/moc_track_content_object_item.cxx"

View File

@@ -0,0 +1,109 @@
#include "track.h"
#include "gui/tracks/track_item.h"
#include "gui/tracks/track_content_object_item.h"
#include "gui/tracks/track_container_scene.h"
TrackItem::TrackItem( TrackContainerScene * _scene, track * _track )
{
m_scene = _scene;
m_track = _track;
// create views for already existing TCOs
const track::tcoVector & tcos = m_track->getTCOs();
for( track::tcoVector::const_iterator it = tcos.begin(); it != tcos.end(); ++it )
{
addTCO( *it );
}
QObject * obj = _track;
connect( obj, SIGNAL( trackContentObjectAdded( trackContentObject * ) ),
this, SLOT( addTCO( trackContentObject * ) ),
Qt::QueuedConnection );
connect( obj, SIGNAL( trackContentObjectRemoved( trackContentObject * ) ),
this, SLOT( removeTCO( trackContentObject * ) ) );
}
/* WTF?!?! */
TrackItem::~TrackItem()
{
for( QMap<trackContentObject*, TrackContentObjectItem*>::iterator i = m_tcoItems.begin();
i != m_tcoItems.end(); ++i )
{
TrackContentObjectItem * item = i.value();
m_scene->removeItem(item);
m_tcoItems.erase(i);
delete item;
}
}
void TrackItem::addTCO( trackContentObject * _tco )
{
TrackContentObjectItem * tcoItem = new TrackContentObjectItem( this, _tco );
// TODO refactor to private updateTCOGeometry
tcoItem->setPos( tcoItem->x(), y() );
m_tcoItems.insert( _tco, tcoItem );
m_scene->addItem( tcoItem );
}
void TrackItem::removeTCO( trackContentObject * _tco )
{
QMap<trackContentObject*, TrackContentObjectItem*>::iterator i =
m_tcoItems.find( _tco );
if( i != m_tcoItems.end() && i.key() == _tco )
{
TrackContentObjectItem * item = i.value();
m_scene->removeItem(*i);
m_tcoItems.erase(i);
delete item;
}
}
void TrackItem::setHeight( float _height )
{
m_rect.setHeight( _height );
for( QMap<trackContentObject*, TrackContentObjectItem*>::const_iterator it = m_tcoItems.constBegin();
it != m_tcoItems.constEnd(); ++it )
{
(*it)->updateGeometry();
}
}
void TrackItem::setY( float _y )
{
//printf("TRK %lld: setY(%.2f)\n", m_track, _y);
m_rect.moveTop( _y );
for( QMap<trackContentObject*, TrackContentObjectItem*>::const_iterator it = m_tcoItems.constBegin();
it != m_tcoItems.constEnd(); ++it )
{
(*it)->setPos( (*it)->x(), y() );
}
}
float TrackItem::height()
{
return m_rect.height();
}
float TrackItem::y()
{
return m_rect.y();
}
#include "gui/tracks/moc_track_item.cxx"