Merge branch 'master' into cmake_dist
# Conflicts: # include/ConfigManager.h # include/Engine.h # plugins/CMakeLists.txt # plugins/vst_base/CMakeLists.txt # plugins/vst_base/Win64/CMakeLists.txt # src/core/Engine.cpp
This commit is contained in:
@@ -31,7 +31,6 @@
|
||||
#include "ProjectJournal.h"
|
||||
#include "BBTrackContainer.h"
|
||||
#include "Song.h"
|
||||
#include "TextFloat.h"
|
||||
#include "embed.h"
|
||||
|
||||
int AutomationPattern::s_quantization = 1;
|
||||
@@ -107,7 +106,7 @@ AutomationPattern::~AutomationPattern()
|
||||
|
||||
|
||||
|
||||
void AutomationPattern::addObject( AutomatableModel * _obj, bool _search_dup )
|
||||
bool AutomationPattern::addObject( AutomatableModel * _obj, bool _search_dup )
|
||||
{
|
||||
if( _search_dup )
|
||||
{
|
||||
@@ -115,10 +114,8 @@ void AutomationPattern::addObject( AutomatableModel * _obj, bool _search_dup )
|
||||
it != m_objects.end(); ++it )
|
||||
{
|
||||
if( *it == _obj )
|
||||
{
|
||||
TextFloat::displayMessage( _obj->displayName(), tr( "Model is already connected "
|
||||
"to this pattern." ), embed::getIconPixmap( "automation" ), 2000 );
|
||||
return;
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -138,6 +135,7 @@ void AutomationPattern::addObject( AutomatableModel * _obj, bool _search_dup )
|
||||
|
||||
emit dataChanged();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -61,6 +61,8 @@ ConfigManager::ConfigManager() :
|
||||
m_artworkDir( defaultArtworkDir() ),
|
||||
m_vstDir( m_workingDir + "vst" + QDir::separator() ),
|
||||
m_flDir( QDir::home().absolutePath() ),
|
||||
m_gigDir( m_workingDir + GIG_PATH ),
|
||||
m_sf2Dir( m_workingDir + SF2_PATH ),
|
||||
m_version( defaultVersion() )
|
||||
{
|
||||
if (! qgetenv("LMMS_DATA_DIR").isEmpty())
|
||||
@@ -176,6 +178,16 @@ void ConfigManager::setBackgroundArtwork( const QString & _ba )
|
||||
#endif
|
||||
}
|
||||
|
||||
void ConfigManager::setGIGDir(const QString &gd)
|
||||
{
|
||||
m_gigDir = gd;
|
||||
}
|
||||
|
||||
void ConfigManager::setSF2Dir(const QString &sfd)
|
||||
{
|
||||
m_sf2Dir = sfd;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -237,31 +249,6 @@ void ConfigManager::setValue( const QString & _class,
|
||||
|
||||
|
||||
|
||||
#ifdef LMMS_BUILD_WIN32
|
||||
#include <QLibrary>
|
||||
#include <shlobj.h>
|
||||
|
||||
// taken from qt-win-opensource-src-4.2.2/src/corelib/io/qsettings.cpp
|
||||
static QString windowsConfigPath( int _type )
|
||||
{
|
||||
QString result;
|
||||
|
||||
QLibrary library( "shell32" );
|
||||
typedef BOOL( WINAPI* GetSpecialFolderPath )( HWND, char *, int, BOOL );
|
||||
GetSpecialFolderPath SHGetSpecialFolderPath = (GetSpecialFolderPath)
|
||||
library.resolve( "SHGetSpecialFolderPathA" );
|
||||
if( SHGetSpecialFolderPath )
|
||||
{
|
||||
char path[MAX_PATH];
|
||||
SHGetSpecialFolderPath( 0, path, _type, false );
|
||||
result = QString::fromLocal8Bit( path );
|
||||
}
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
void ConfigManager::loadConfigFile()
|
||||
{
|
||||
// read the XML file and create DOM tree
|
||||
@@ -336,6 +323,9 @@ void ConfigManager::loadConfigFile()
|
||||
}
|
||||
}
|
||||
setWorkingDir( value( "paths", "workingdir" ) );
|
||||
|
||||
setGIGDir( value( "paths", "gigdir" ) == "" ? gigDir() : value( "paths", "gigdir" ) );
|
||||
setSF2Dir( value( "paths", "sf2dir" ) == "" ? sf2Dir() : value( "paths", "sf2dir" ) );
|
||||
setVSTDir( value( "paths", "vstdir" ) );
|
||||
setFLDir( value( "paths", "fldir" ) );
|
||||
setLADSPADir( value( "paths", "laddir" ) );
|
||||
@@ -363,10 +353,10 @@ void ConfigManager::loadConfigFile()
|
||||
!QDir( m_vstDir ).exists() )
|
||||
{
|
||||
#ifdef LMMS_BUILD_WIN32
|
||||
m_vstDir = windowsConfigPath( CSIDL_PROGRAM_FILES ) +
|
||||
QDir::separator() + "VstPlugins";
|
||||
QString programFiles = QString::fromLocal8Bit( getenv( "ProgramFiles" ) );
|
||||
m_vstDir = programFiles + QDir::separator() + "VstPlugins" + QDir::separator();
|
||||
#else
|
||||
m_vstDir = ensureTrailingSlash( QDir::home().absolutePath() );
|
||||
m_vstDir = m_workingDir + "plugins/vst/";
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -385,6 +375,7 @@ void ConfigManager::loadConfigFile()
|
||||
#else
|
||||
m_ladDir = qApp->applicationDirPath() + '/' + LIB_DIR + "/ladspa/";
|
||||
#endif
|
||||
m_ladDir += ","+userLadspaDir();
|
||||
}
|
||||
|
||||
#ifdef LMMS_HAVE_STK
|
||||
@@ -422,8 +413,14 @@ void ConfigManager::loadConfigFile()
|
||||
if( QDir( m_workingDir ).exists() )
|
||||
{
|
||||
QDir().mkpath( userProjectsDir() );
|
||||
QDir().mkpath( userTemplateDir() );
|
||||
QDir().mkpath( userSamplesDir() );
|
||||
QDir().mkpath( userPresetsDir() );
|
||||
QDir().mkpath( userGigDir() );
|
||||
QDir().mkpath( userSf2Dir() );
|
||||
QDir().mkpath( userVstDir() );
|
||||
QDir().mkpath( userLadspaDir() );
|
||||
|
||||
}
|
||||
|
||||
upgrade();
|
||||
@@ -438,6 +435,8 @@ void ConfigManager::saveConfigFile()
|
||||
setValue( "paths", "workingdir", m_workingDir );
|
||||
setValue( "paths", "vstdir", m_vstDir );
|
||||
setValue( "paths", "fldir", m_flDir );
|
||||
setValue( "paths", "gigdir", m_gigDir );
|
||||
setValue( "paths", "sf2dir", m_sf2Dir );
|
||||
setValue( "paths", "laddir", m_ladDir );
|
||||
#ifdef LMMS_HAVE_STK
|
||||
setValue( "paths", "stkdir", m_stkDir );
|
||||
|
||||
@@ -52,9 +52,13 @@ DummyTrackContainer * Engine::s_dummyTC = NULL;
|
||||
|
||||
void Engine::init()
|
||||
{
|
||||
Engine *engine = inst();
|
||||
|
||||
emit engine->initProgress(tr("Generating wavetables"));
|
||||
// generate (load from file) bandlimited wavetables
|
||||
BandLimitedWave::generateWaves();
|
||||
|
||||
emit engine->initProgress(tr("Initializing data structures"));
|
||||
s_projectJournal = new ProjectJournal;
|
||||
s_mixer = new Mixer;
|
||||
s_song = new Song;
|
||||
@@ -65,11 +69,13 @@ void Engine::init()
|
||||
|
||||
s_projectJournal->setJournalling( true );
|
||||
|
||||
emit engine->initProgress(tr("Opening audio and midi devices"));
|
||||
s_mixer->initDevices();
|
||||
|
||||
PresetPreviewPlayHandle::init();
|
||||
s_dummyTC = new DummyTrackContainer;
|
||||
|
||||
emit engine->initProgress(tr("Launching mixer threads"));
|
||||
s_mixer->startProcessing();
|
||||
}
|
||||
|
||||
@@ -114,3 +120,5 @@ void Engine::updateFramesPerTick()
|
||||
s_framesPerTick = s_mixer->processingSampleRate() * 60.0f * 4 /
|
||||
DefaultTicksPerTact / s_song->getTempo();
|
||||
}
|
||||
|
||||
Engine * Engine::s_instanceOfMe = NULL;
|
||||
|
||||
@@ -98,8 +98,8 @@ inline void FxChannel::processed()
|
||||
|
||||
void FxChannel::incrementDeps()
|
||||
{
|
||||
m_dependenciesMet.ref();
|
||||
if( m_dependenciesMet >= m_receives.size() && ! m_queued )
|
||||
int i = m_dependenciesMet.fetchAndAddOrdered( 1 ) + 1;
|
||||
if( i >= m_receives.size() && ! m_queued )
|
||||
{
|
||||
m_queued = true;
|
||||
MixerWorkerThread::addJob( this );
|
||||
@@ -327,6 +327,19 @@ void FxMixer::deleteChannel( int index )
|
||||
for( int i = index; i < m_fxChannels.size(); ++i )
|
||||
{
|
||||
validateChannelName( i, i + 1 );
|
||||
|
||||
// set correct channel index
|
||||
m_fxChannels[i]->m_channelIndex = i;
|
||||
|
||||
// now check all routes and update names of the send models
|
||||
foreach( FxRoute * r, m_fxChannels[i]->m_sends )
|
||||
{
|
||||
r->updateName();
|
||||
}
|
||||
foreach( FxRoute * r, m_fxChannels[i]->m_receives )
|
||||
{
|
||||
r->updateName();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -364,18 +377,9 @@ void FxMixer::moveChannelLeft( int index )
|
||||
{
|
||||
inst->effectChannelModel()->setValue(a);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// actually do the swap
|
||||
FxChannel * tmpChannel = m_fxChannels[a];
|
||||
m_fxChannels[a] = m_fxChannels[b];
|
||||
m_fxChannels[b] = tmpChannel;
|
||||
|
||||
validateChannelName( a, b );
|
||||
validateChannelName( b, a );
|
||||
}
|
||||
|
||||
|
||||
@@ -761,22 +765,9 @@ void FxMixer::loadSettings( const QDomElement & _this )
|
||||
|
||||
void FxMixer::validateChannelName( int index, int oldIndex )
|
||||
{
|
||||
FxChannel * fxc = m_fxChannels[ index ];
|
||||
if( fxc->m_name == tr( "FX %1" ).arg( oldIndex ) )
|
||||
if( m_fxChannels[index]->m_name == tr( "FX %1" ).arg( oldIndex ) )
|
||||
{
|
||||
fxc->m_name = tr( "FX %1" ).arg( index );
|
||||
}
|
||||
// set correct channel index
|
||||
fxc->m_channelIndex = index;
|
||||
|
||||
// now check all routes and update names of the send models
|
||||
foreach( FxRoute * r, fxc->m_sends )
|
||||
{
|
||||
r->updateName();
|
||||
}
|
||||
foreach( FxRoute * r, fxc->m_receives )
|
||||
{
|
||||
r->updateName();
|
||||
m_fxChannels[index]->m_name = tr( "FX %1" ).arg( index );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -28,8 +28,7 @@
|
||||
|
||||
InstrumentPlayHandle::InstrumentPlayHandle( Instrument * instrument, InstrumentTrack* instrumentTrack ) :
|
||||
PlayHandle( TypeInstrumentPlayHandle ),
|
||||
m_instrument( instrument ),
|
||||
m_instrumentTrack( instrumentTrack )
|
||||
m_instrument( instrument )
|
||||
{
|
||||
setAudioPort( instrumentTrack->audioPort() );
|
||||
}
|
||||
|
||||
@@ -930,15 +930,7 @@ void Mixer::fifoWriter::finish()
|
||||
|
||||
void Mixer::fifoWriter::run()
|
||||
{
|
||||
// set denormal protection for this thread
|
||||
#ifdef __SSE3__
|
||||
/* DAZ flag */
|
||||
_MM_SET_DENORMALS_ZERO_MODE( _MM_DENORMALS_ZERO_ON );
|
||||
#endif
|
||||
#ifdef __SSE__
|
||||
/* FTZ flag */
|
||||
_MM_SET_FLUSH_ZERO_MODE( _MM_FLUSH_ZERO_ON );
|
||||
#endif
|
||||
disable_denormals();
|
||||
|
||||
#if 0
|
||||
#ifdef LMMS_BUILD_LINUX
|
||||
|
||||
@@ -29,12 +29,7 @@
|
||||
#include "ThreadableJob.h"
|
||||
#include "Mixer.h"
|
||||
|
||||
#ifdef __SSE__
|
||||
#include <xmmintrin.h>
|
||||
#endif
|
||||
#ifdef __SSE3__
|
||||
#include <pmmintrin.h>
|
||||
#endif
|
||||
#include "denormals.h"
|
||||
|
||||
MixerWorkerThread::JobQueue MixerWorkerThread::globalJobQueue;
|
||||
QWaitCondition * MixerWorkerThread::queueReadyWaitCond = NULL;
|
||||
@@ -159,15 +154,8 @@ void MixerWorkerThread::startAndWaitForJobs()
|
||||
|
||||
void MixerWorkerThread::run()
|
||||
{
|
||||
// set denormal protection for this thread
|
||||
#ifdef __SSE3__
|
||||
/* DAZ flag */
|
||||
_MM_SET_DENORMALS_ZERO_MODE( _MM_DENORMALS_ZERO_ON );
|
||||
#endif
|
||||
#ifdef __SSE__
|
||||
/* FTZ flag */
|
||||
_MM_SET_FLUSH_ZERO_MODE( _MM_FLUSH_ZERO_ON );
|
||||
#endif
|
||||
disable_denormals();
|
||||
|
||||
QMutex m;
|
||||
while( m_quit == false )
|
||||
{
|
||||
|
||||
@@ -97,6 +97,15 @@ void ProjectJournal::redo()
|
||||
}
|
||||
}
|
||||
|
||||
bool ProjectJournal::canUndo() const
|
||||
{
|
||||
return !m_undoCheckPoints.isEmpty();
|
||||
}
|
||||
|
||||
bool ProjectJournal::canRedo() const
|
||||
{
|
||||
return !m_redoCheckPoints.isEmpty();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -94,7 +94,6 @@ Song::Song() :
|
||||
m_errors( new QList<QString>() ),
|
||||
m_playMode( Mode_None ),
|
||||
m_length( 0 ),
|
||||
m_trackToPlay( NULL ),
|
||||
m_patternToPlay( NULL ),
|
||||
m_loopPattern( false ),
|
||||
m_elapsedMilliSeconds( 0 ),
|
||||
@@ -199,14 +198,17 @@ void Song::savePos()
|
||||
|
||||
void Song::processNextBuffer()
|
||||
{
|
||||
// if not playing, nothing to do
|
||||
if( m_playing == false )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
TrackList trackList;
|
||||
int tcoNum = -1;
|
||||
int tcoNum = -1; // track content object number
|
||||
|
||||
// determine the list of tracks to play and the track content object
|
||||
// (TCO) number
|
||||
switch( m_playMode )
|
||||
{
|
||||
case Mode_PlaySong:
|
||||
@@ -218,10 +220,6 @@ void Song::processNextBuffer()
|
||||
}
|
||||
break;
|
||||
|
||||
case Mode_PlayTrack:
|
||||
trackList.push_back( m_trackToPlay );
|
||||
break;
|
||||
|
||||
case Mode_PlayBB:
|
||||
if( Engine::getBBTrackContainer()->numOfBBs() > 0 )
|
||||
{
|
||||
@@ -247,6 +245,7 @@ void Song::processNextBuffer()
|
||||
|
||||
}
|
||||
|
||||
// if we have no tracks to play, nothing to do
|
||||
if( trackList.empty() == true )
|
||||
{
|
||||
return;
|
||||
@@ -259,6 +258,8 @@ void Song::processNextBuffer()
|
||||
|
||||
if( checkLoop )
|
||||
{
|
||||
// if looping-mode is enabled and we are outside of the looping
|
||||
// range, go to the beginning of the range
|
||||
if( m_playPos[m_playMode] < tl->loopBegin() ||
|
||||
m_playPos[m_playMode] >= tl->loopEnd() )
|
||||
{
|
||||
@@ -269,16 +270,13 @@ void Song::processNextBuffer()
|
||||
}
|
||||
}
|
||||
|
||||
f_cnt_t totalFramesPlayed = 0;
|
||||
f_cnt_t framesPlayed = 0;
|
||||
const float framesPerTick = Engine::framesPerTick();
|
||||
|
||||
while( totalFramesPlayed < Engine::mixer()->framesPerPeriod() )
|
||||
while( framesPlayed < Engine::mixer()->framesPerPeriod() )
|
||||
{
|
||||
m_vstSyncController.update();
|
||||
|
||||
f_cnt_t playedFrames = Engine::mixer()->framesPerPeriod() -
|
||||
totalFramesPlayed;
|
||||
|
||||
float currentFrame = m_playPos[m_playMode].currentFrame();
|
||||
// did we play a tick?
|
||||
if( currentFrame >= framesPerTick )
|
||||
@@ -335,6 +333,9 @@ void Song::processNextBuffer()
|
||||
m_vstSyncController.startCycle(
|
||||
tl->loopBegin().getTicks(), tl->loopEnd().getTicks() );
|
||||
|
||||
// if looping-mode is enabled and we have got
|
||||
// past the looping range, return to the
|
||||
// beginning of the range
|
||||
if( m_playPos[m_playMode] >= tl->loopEnd() )
|
||||
{
|
||||
m_playPos[m_playMode].setTicks( tl->loopBegin().getTicks() );
|
||||
@@ -353,23 +354,26 @@ void Song::processNextBuffer()
|
||||
m_playPos[m_playMode].setCurrentFrame( currentFrame );
|
||||
}
|
||||
|
||||
f_cnt_t lastFrames = ( f_cnt_t )framesPerTick -
|
||||
( f_cnt_t )currentFrame;
|
||||
f_cnt_t framesToPlay =
|
||||
Engine::mixer()->framesPerPeriod() - framesPlayed;
|
||||
|
||||
f_cnt_t framesLeft = ( f_cnt_t )framesPerTick -
|
||||
( f_cnt_t )currentFrame;
|
||||
// skip last frame fraction
|
||||
if( lastFrames == 0 )
|
||||
if( framesLeft == 0 )
|
||||
{
|
||||
++totalFramesPlayed;
|
||||
++framesPlayed;
|
||||
m_playPos[m_playMode].setCurrentFrame( currentFrame
|
||||
+ 1.0f );
|
||||
continue;
|
||||
}
|
||||
// do we have some samples left in this tick but these are
|
||||
// less then samples we have to play?
|
||||
if( lastFrames < playedFrames )
|
||||
// do we have samples left in this tick but these are less
|
||||
// than samples we have to play?
|
||||
if( framesLeft < framesToPlay )
|
||||
{
|
||||
// then set played_samples to remaining samples, the
|
||||
// then set framesToPlay to remaining samples, the
|
||||
// rest will be played in next loop
|
||||
playedFrames = lastFrames;
|
||||
framesToPlay = framesLeft;
|
||||
}
|
||||
|
||||
if( ( f_cnt_t ) currentFrame == 0 )
|
||||
@@ -378,25 +382,25 @@ void Song::processNextBuffer()
|
||||
{
|
||||
m_globalAutomationTrack->play(
|
||||
m_playPos[m_playMode],
|
||||
playedFrames,
|
||||
totalFramesPlayed, tcoNum );
|
||||
framesToPlay,
|
||||
framesPlayed, tcoNum );
|
||||
}
|
||||
|
||||
// loop through all tracks and play them
|
||||
for( int i = 0; i < trackList.size(); ++i )
|
||||
{
|
||||
trackList[i]->play( m_playPos[m_playMode],
|
||||
playedFrames,
|
||||
totalFramesPlayed, tcoNum );
|
||||
framesToPlay,
|
||||
framesPlayed, tcoNum );
|
||||
}
|
||||
}
|
||||
|
||||
// update frame-counters
|
||||
totalFramesPlayed += playedFrames;
|
||||
m_playPos[m_playMode].setCurrentFrame( playedFrames +
|
||||
framesPlayed += framesToPlay;
|
||||
m_playPos[m_playMode].setCurrentFrame( framesToPlay +
|
||||
currentFrame );
|
||||
m_elapsedMilliSeconds +=
|
||||
( ( playedFrames / framesPerTick ) * 60 * 1000 / 48 )
|
||||
( ( framesToPlay / framesPerTick ) * 60 * 1000 / 48 )
|
||||
/ getTempo();
|
||||
m_elapsedTacts = m_playPos[Mode_PlaySong].getTact();
|
||||
m_elapsedTicks = ( m_playPos[Mode_PlaySong].getTicks() % ticksPerTact() ) / 48;
|
||||
@@ -470,28 +474,6 @@ void Song::playAndRecord()
|
||||
|
||||
|
||||
|
||||
void Song::playTrack( Track * trackToPlay )
|
||||
{
|
||||
if( isStopped() == false )
|
||||
{
|
||||
stop();
|
||||
}
|
||||
m_trackToPlay = trackToPlay;
|
||||
|
||||
m_playMode = Mode_PlayTrack;
|
||||
m_playing = true;
|
||||
m_paused = false;
|
||||
|
||||
m_vstSyncController.setPlaybackState( true );
|
||||
|
||||
savePos();
|
||||
|
||||
emit playbackStateChanged();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void Song::playBB()
|
||||
{
|
||||
if( isStopped() == false )
|
||||
@@ -847,8 +829,10 @@ void Song::clearProject()
|
||||
// create new file
|
||||
void Song::createNewProject()
|
||||
{
|
||||
QString defaultTemplate = ConfigManager::inst()->userProjectsDir()
|
||||
+ "templates/default.mpt";
|
||||
|
||||
QString defaultTemplate = ConfigManager::inst()->userTemplateDir()
|
||||
+ "default.mpt";
|
||||
|
||||
|
||||
if( QFile::exists( defaultTemplate ) )
|
||||
{
|
||||
|
||||
@@ -78,11 +78,6 @@
|
||||
*/
|
||||
const int RESIZE_GRIP_WIDTH = 4;
|
||||
|
||||
/*! The size of the track buttons in pixels
|
||||
*/
|
||||
const int TRACK_OP_BTN_WIDTH = 20;
|
||||
const int TRACK_OP_BTN_HEIGHT = 14;
|
||||
|
||||
|
||||
/*! A pointer for that text bubble used when moving segments, etc.
|
||||
*
|
||||
@@ -108,7 +103,7 @@ TrackContentObject::TrackContentObject( Track * track ) :
|
||||
m_name( QString::null ),
|
||||
m_startPosition(),
|
||||
m_length(),
|
||||
m_mutedModel( false, this, tr( "Muted" ) ),
|
||||
m_mutedModel( false, this, tr( "Mute" ) ),
|
||||
m_selectViewOnCreate( false )
|
||||
{
|
||||
if( getTrack() )
|
||||
@@ -1688,13 +1683,18 @@ void TrackOperationsWidget::paintEvent( QPaintEvent * pe )
|
||||
|
||||
|
||||
|
||||
|
||||
/*! \brief Clone this track
|
||||
*
|
||||
*/
|
||||
void TrackOperationsWidget::cloneTrack()
|
||||
{
|
||||
m_trackView->getTrack()->clone();
|
||||
TrackContainerView *tcView = m_trackView->trackContainerView();
|
||||
|
||||
Track *newTrack = m_trackView->getTrack()->clone();
|
||||
TrackView *newTrackView = tcView->createTrackView( newTrack );
|
||||
|
||||
int index = tcView->trackViews().indexOf( m_trackView );
|
||||
tcView->moveTrackView( newTrackView, index + 1 );
|
||||
}
|
||||
|
||||
|
||||
@@ -1810,7 +1810,7 @@ Track::Track( TrackTypes type, TrackContainer * tc ) :
|
||||
m_trackContainer( tc ), /*!< The track container object */
|
||||
m_type( type ), /*!< The track type */
|
||||
m_name(), /*!< The track's name */
|
||||
m_mutedModel( false, this, tr( "Muted" ) ),
|
||||
m_mutedModel( false, this, tr( "Mute" ) ),
|
||||
/*!< For controlling track muting */
|
||||
m_soloModel( false, this, tr( "Solo" ) ),
|
||||
/*!< For controlling track soloing */
|
||||
@@ -1904,12 +1904,12 @@ Track * Track::create( const QDomElement & element, TrackContainer * tc )
|
||||
/*! \brief Clone a track from this track
|
||||
*
|
||||
*/
|
||||
void Track::clone()
|
||||
Track * Track::clone()
|
||||
{
|
||||
QDomDocument doc;
|
||||
QDomElement parent = doc.createElement( "clone" );
|
||||
saveState( doc, parent );
|
||||
create( parent.firstChild().toElement(), m_trackContainer );
|
||||
return create( parent.firstChild().toElement(), m_trackContainer );
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -27,13 +27,7 @@
|
||||
#include "lmmsversion.h"
|
||||
#include "versioninfo.h"
|
||||
|
||||
// denormals stripping
|
||||
#ifdef __SSE__
|
||||
#include <xmmintrin.h>
|
||||
#endif
|
||||
#ifdef __SSE3__
|
||||
#include <pmmintrin.h>
|
||||
#endif
|
||||
#include "denormals.h"
|
||||
|
||||
#include <QFileInfo>
|
||||
#include <QLocale>
|
||||
@@ -103,15 +97,7 @@ int main( int argc, char * * argv )
|
||||
// intialize RNG
|
||||
srand( getpid() + time( 0 ) );
|
||||
|
||||
// set denormal protection for this thread
|
||||
#ifdef __SSE3__
|
||||
/* DAZ flag */
|
||||
_MM_SET_DENORMALS_ZERO_MODE( _MM_DENORMALS_ZERO_ON );
|
||||
#endif
|
||||
#ifdef __SSE__
|
||||
/* FTZ flag */
|
||||
_MM_SET_FLUSH_ZERO_MODE( _MM_FLUSH_ZERO_ON );
|
||||
#endif
|
||||
disable_denormals();
|
||||
|
||||
bool core_only = false;
|
||||
bool fullscreen = true;
|
||||
@@ -217,12 +203,10 @@ int main( int argc, char * * argv )
|
||||
else if( argc > i+1 && ( QString( argv[i] ) == "--upgrade" ||
|
||||
QString( argv[i] ) == "-u" ) )
|
||||
{
|
||||
QString inFile( argv[i + 1] );
|
||||
DataFile dataFile( inFile );
|
||||
DataFile dataFile( QString::fromLocal8Bit( argv[i + 1] ) );
|
||||
if (argc > i+2)
|
||||
{
|
||||
const QString outFile = argv[i + 2];
|
||||
dataFile.writeFile( outFile );
|
||||
dataFile.writeFile( QString::fromLocal8Bit( argv[i + 2] ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -246,7 +230,7 @@ int main( int argc, char * * argv )
|
||||
else if( argc > i && ( QString( argv[i] ) == "--dump" ||
|
||||
QString( argv[i] ) == "-d" ) )
|
||||
{
|
||||
QFile f( argv[i + 1] );
|
||||
QFile f( QString::fromLocal8Bit( argv[i + 1] ) );
|
||||
f.open( QIODevice::ReadOnly );
|
||||
QString d = qUncompress( f.readAll() );
|
||||
printf( "%s\n", d.toUtf8().constData() );
|
||||
@@ -255,14 +239,14 @@ int main( int argc, char * * argv )
|
||||
else if( argc > i && ( QString( argv[i] ) == "--render" ||
|
||||
QString( argv[i] ) == "-r" ) )
|
||||
{
|
||||
file_to_load = QString( argv[i + 1] );
|
||||
file_to_load = QString::fromLocal8Bit( argv[i + 1] );
|
||||
render_out = baseName( file_to_load ) + ".";
|
||||
++i;
|
||||
}
|
||||
else if( argc > i && ( QString( argv[i] ) == "--output" ||
|
||||
QString( argv[i] ) == "-o" ) )
|
||||
{
|
||||
render_out = baseName( QString( argv[i + 1] ) ) + ".";
|
||||
render_out = baseName( QString::fromLocal8Bit( argv[i + 1] ) ) + ".";
|
||||
++i;
|
||||
}
|
||||
else if( argc > i &&
|
||||
@@ -386,7 +370,7 @@ int main( int argc, char * * argv )
|
||||
else if( argc > i &&
|
||||
( QString( argv[i] ) == "--import" ) )
|
||||
{
|
||||
file_to_import = argv[i+1];
|
||||
file_to_import = QString::fromLocal8Bit( argv[i+1] );
|
||||
++i;
|
||||
// exit after import? (only for debugging)
|
||||
if( argc > i && QString( argv[i+1] ) == "-e" )
|
||||
@@ -396,7 +380,7 @@ int main( int argc, char * * argv )
|
||||
}
|
||||
else if( argc > i && ( QString( argv[i] ) == "--profile" || QString( argv[i] ) == "-p" ) )
|
||||
{
|
||||
profilerOutputFile = argv[i+1];
|
||||
profilerOutputFile = QString::fromLocal8Bit( argv[i+1] );
|
||||
++i;
|
||||
}
|
||||
else
|
||||
@@ -407,7 +391,7 @@ int main( int argc, char * * argv )
|
||||
"Try \"%s --help\" for more information.\n\n", argv[i], argv[0] );
|
||||
return( EXIT_FAILURE );
|
||||
}
|
||||
file_to_load = argv[i];
|
||||
file_to_load = QString::fromLocal8Bit( argv[i] );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -35,6 +35,7 @@
|
||||
#include "ProjectJournal.h"
|
||||
#include "RenameDialog.h"
|
||||
#include "StringPairDrag.h"
|
||||
#include "TextFloat.h"
|
||||
#include "ToolTip.h"
|
||||
|
||||
|
||||
@@ -420,7 +421,15 @@ void AutomationPatternView::dropEvent( QDropEvent * _de )
|
||||
journallingObject( val.toInt() ) );
|
||||
if( mod != NULL )
|
||||
{
|
||||
m_pat->addObject( mod );
|
||||
bool added = m_pat->addObject( mod );
|
||||
if ( !added )
|
||||
{
|
||||
TextFloat::displayMessage( mod->displayName(),
|
||||
tr( "Model is already connected "
|
||||
"to this pattern." ),
|
||||
embed::getIconPixmap( "automation" ),
|
||||
2000 );
|
||||
}
|
||||
}
|
||||
update();
|
||||
|
||||
|
||||
@@ -55,6 +55,7 @@ SET(LMMS_SRCS
|
||||
gui/widgets/InstrumentFunctionViews.cpp
|
||||
gui/widgets/InstrumentMidiIOView.cpp
|
||||
gui/widgets/InstrumentSoundShapingView.cpp
|
||||
gui/widgets/LeftRightNav.cpp
|
||||
gui/widgets/Knob.cpp
|
||||
gui/widgets/LadspaControlView.cpp
|
||||
gui/widgets/LcdSpinBox.cpp
|
||||
|
||||
@@ -30,6 +30,8 @@
|
||||
#include "embed.h"
|
||||
#include "PluginFactory.h"
|
||||
|
||||
#include <QLabel>
|
||||
|
||||
|
||||
EffectSelectDialog::EffectSelectDialog( QWidget * _parent ) :
|
||||
QDialog( _parent ),
|
||||
@@ -168,25 +170,64 @@ void EffectSelectDialog::rowChanged( const QModelIndex & _idx,
|
||||
{
|
||||
m_currentSelection = m_effectKeys[m_model.mapToSource( _idx ).row()];
|
||||
}
|
||||
if( m_currentSelection.desc && m_currentSelection.desc->subPluginFeatures )
|
||||
if( m_currentSelection.desc )
|
||||
{
|
||||
m_descriptionWidget = new QWidget;
|
||||
QVBoxLayout * l = new QVBoxLayout( m_descriptionWidget );
|
||||
l->setMargin( 4 );
|
||||
l->setSpacing( 0 );
|
||||
|
||||
ui->scrollArea->setWidget( m_descriptionWidget );
|
||||
QHBoxLayout *hbox = new QHBoxLayout( m_descriptionWidget );
|
||||
|
||||
m_currentSelection.desc->subPluginFeatures->
|
||||
fillDescriptionWidget( m_descriptionWidget, &m_currentSelection );
|
||||
foreach( QWidget * w, m_descriptionWidget->findChildren<QWidget *>() )
|
||||
{
|
||||
if( w->parent() == m_descriptionWidget )
|
||||
{
|
||||
l->addWidget( w );
|
||||
}
|
||||
}
|
||||
l->setSizeConstraint( QLayout::SetFixedSize );
|
||||
Plugin::Descriptor const & descriptor = *( m_currentSelection.desc );
|
||||
|
||||
if ( descriptor.logo )
|
||||
{
|
||||
QLabel *logoLabel = new QLabel( m_descriptionWidget );
|
||||
logoLabel->setPixmap( descriptor.logo->pixmap() );
|
||||
logoLabel->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
|
||||
|
||||
hbox->addWidget( logoLabel );
|
||||
hbox->setAlignment( logoLabel, Qt::AlignTop);
|
||||
}
|
||||
|
||||
QWidget *textualInfoWidget = new QWidget( m_descriptionWidget );
|
||||
|
||||
hbox->addWidget(textualInfoWidget);
|
||||
|
||||
QVBoxLayout * textWidgetLayout = new QVBoxLayout( textualInfoWidget);
|
||||
textWidgetLayout->setMargin( 4 );
|
||||
textWidgetLayout->setSpacing( 0 );
|
||||
|
||||
std::string stdName(descriptor.name);
|
||||
if ( stdName != "ladspaeffect" )
|
||||
{
|
||||
QLabel *label = new QLabel(m_descriptionWidget);
|
||||
QString labelText = "<p><b>" + tr("Name") + ":</b> " + QString::fromUtf8(descriptor.displayName) + "</p>";
|
||||
labelText += "<p><b>" + tr("Description") + ":</b> " + QString::fromUtf8(descriptor.description) + "</p>";
|
||||
labelText += "<p><b>" + tr("Author") + ":</b> " + QString::fromUtf8(descriptor.author) + "</p>";
|
||||
|
||||
label->setText(labelText);
|
||||
textWidgetLayout->addWidget(label);
|
||||
}
|
||||
|
||||
if ( m_currentSelection.desc->subPluginFeatures )
|
||||
{
|
||||
QWidget *subWidget = new QWidget(textualInfoWidget);
|
||||
QVBoxLayout * subLayout = new QVBoxLayout( subWidget );
|
||||
subLayout->setMargin( 4 );
|
||||
subLayout->setSpacing( 0 );
|
||||
m_currentSelection.desc->subPluginFeatures->
|
||||
fillDescriptionWidget( subWidget, &m_currentSelection );
|
||||
foreach( QWidget * w, subWidget->findChildren<QWidget *>() )
|
||||
{
|
||||
if( w->parent() == subWidget )
|
||||
{
|
||||
subLayout->addWidget( w );
|
||||
}
|
||||
}
|
||||
|
||||
textWidgetLayout->addWidget(subWidget);
|
||||
}
|
||||
|
||||
ui->scrollArea->setWidget( m_descriptionWidget );
|
||||
m_descriptionWidget->show();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
#include <QMdiArea>
|
||||
#include <QMdiSubWindow>
|
||||
#include <QMessageBox>
|
||||
#include <QShortcut>
|
||||
|
||||
#include "FileBrowser.h"
|
||||
#include "BBTrackContainer.h"
|
||||
@@ -98,6 +99,10 @@ FileBrowser::FileBrowser(const QString & directories, const QString & filter,
|
||||
|
||||
addContentWidget( ops );
|
||||
|
||||
// Whenever the FileBrowser has focus, Ctrl+F should direct focus to its filter box.
|
||||
QShortcut *filterFocusShortcut = new QShortcut( QKeySequence( QKeySequence::Find ), this, SLOT(giveFocusToFilter()) );
|
||||
filterFocusShortcut->setContext(Qt::WidgetWithChildrenShortcut);
|
||||
|
||||
reloadTree();
|
||||
show();
|
||||
}
|
||||
@@ -254,7 +259,15 @@ void FileBrowser::reloadTree( void )
|
||||
filterItems( text );
|
||||
}
|
||||
|
||||
|
||||
void FileBrowser::giveFocusToFilter()
|
||||
{
|
||||
if (!m_filterEdit->hasFocus())
|
||||
{
|
||||
// give focus to filter text box and highlight its text for quick editing if not previously focused
|
||||
m_filterEdit->setFocus();
|
||||
m_filterEdit->selectAll();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void FileBrowser::addItems(const QString & path )
|
||||
@@ -872,8 +885,6 @@ bool Directory::addItems(const QString & path )
|
||||
addChild( new Directory( cur_file, path,
|
||||
m_filter ) );
|
||||
m_dirCount++;
|
||||
//recurse for each dir
|
||||
addItems( path + cur_file + QDir::separator() );
|
||||
}
|
||||
|
||||
added_something = true;
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>585</width>
|
||||
<height>547</height>
|
||||
<height>550</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
@@ -40,41 +40,20 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>200</height>
|
||||
</size>
|
||||
<widget class="QScrollArea" name="scrollArea">
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::NoFrame</enum>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>210</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Plugin description</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QScrollArea" name="scrollArea">
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::NoFrame</enum>
|
||||
</property>
|
||||
<widget class="QWidget" name="scrollAreaWidgetContents">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>497</width>
|
||||
<height>109</height>
|
||||
</rect>
|
||||
</property>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
<widget class="QWidget" name="scrollAreaWidgetContents">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>497</width>
|
||||
<height>109</height>
|
||||
</rect>
|
||||
</property>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
|
||||
@@ -267,19 +267,20 @@ void FxMixerView::loadSettings( const QDomElement & _this )
|
||||
|
||||
|
||||
FxMixerView::FxChannelView::FxChannelView(QWidget * _parent, FxMixerView * _mv,
|
||||
int _chIndex )
|
||||
int channelIndex )
|
||||
{
|
||||
m_fxLine = new FxLine(_parent, _mv, _chIndex);
|
||||
m_fxLine = new FxLine(_parent, _mv, channelIndex);
|
||||
|
||||
FxMixer * m = Engine::fxMixer();
|
||||
m_fader = new Fader( &m->effectChannel(_chIndex)->m_volumeModel,
|
||||
tr( "FX Fader %1" ).arg( _chIndex ), m_fxLine );
|
||||
FxChannel *fxChannel = Engine::fxMixer()->effectChannel(channelIndex);
|
||||
|
||||
m_fader = new Fader( &fxChannel->m_volumeModel,
|
||||
tr( "FX Fader %1" ).arg( channelIndex ), m_fxLine );
|
||||
m_fader->move( 16-m_fader->width()/2,
|
||||
m_fxLine->height()-
|
||||
m_fader->height()-5 );
|
||||
|
||||
m_muteBtn = new PixmapButton( m_fxLine, tr( "Mute" ) );
|
||||
m_muteBtn->setModel( &m->effectChannel(_chIndex)->m_muteModel );
|
||||
m_muteBtn->setModel( &fxChannel->m_muteModel );
|
||||
m_muteBtn->setActiveGraphic(
|
||||
embed::getIconPixmap( "led_off" ) );
|
||||
m_muteBtn->setInactiveGraphic(
|
||||
@@ -289,23 +290,34 @@ FxMixerView::FxChannelView::FxChannelView(QWidget * _parent, FxMixerView * _mv,
|
||||
ToolTip::add( m_muteBtn, tr( "Mute this FX channel" ) );
|
||||
|
||||
m_soloBtn = new PixmapButton( m_fxLine, tr( "Solo" ) );
|
||||
m_soloBtn->setModel( &m->effectChannel(_chIndex)->m_soloModel );
|
||||
m_soloBtn->setModel( &fxChannel->m_soloModel );
|
||||
m_soloBtn->setActiveGraphic(
|
||||
embed::getIconPixmap( "led_red" ) );
|
||||
m_soloBtn->setInactiveGraphic(
|
||||
embed::getIconPixmap( "led_off" ) );
|
||||
m_soloBtn->setCheckable( true );
|
||||
m_soloBtn->move( 9, m_fader->y()-21);
|
||||
connect(&m->effectChannel(_chIndex)->m_soloModel, SIGNAL( dataChanged() ),
|
||||
connect(&fxChannel->m_soloModel, SIGNAL( dataChanged() ),
|
||||
_mv, SLOT ( toggledSolo() ) );
|
||||
ToolTip::add( m_soloBtn, tr( "Solo FX channel" ) );
|
||||
|
||||
// Create EffectRack for the channel
|
||||
m_rackView = new EffectRackView( &m->effectChannel(_chIndex)->m_fxChain, _mv->m_racksWidget );
|
||||
m_rackView = new EffectRackView( &fxChannel->m_fxChain, _mv->m_racksWidget );
|
||||
m_rackView->setFixedSize( 245, FxLine::FxLineHeight );
|
||||
}
|
||||
|
||||
|
||||
void FxMixerView::FxChannelView::setChannelIndex( int index )
|
||||
{
|
||||
FxChannel* fxChannel = Engine::fxMixer()->effectChannel( index );
|
||||
|
||||
m_fader->setModel( &fxChannel->m_volumeModel );
|
||||
m_muteBtn->setModel( &fxChannel->m_muteModel );
|
||||
m_soloBtn->setModel( &fxChannel->m_soloModel );
|
||||
m_rackView->setModel( &fxChannel->m_fxChain );
|
||||
}
|
||||
|
||||
|
||||
void FxMixerView::toggledSolo()
|
||||
{
|
||||
Engine::fxMixer()->toggledSolo();
|
||||
@@ -432,53 +444,39 @@ void FxMixerView::deleteUnusedChannels()
|
||||
|
||||
|
||||
|
||||
void FxMixerView::moveChannelLeft(int index)
|
||||
void FxMixerView::moveChannelLeft(int index, int focusIndex)
|
||||
{
|
||||
// can't move master or first channel left or last channel right
|
||||
if( index <= 1 || index >= m_fxChannelViews.size() ) return;
|
||||
|
||||
int selIndex = m_currentFxLine->channelIndex();
|
||||
FxMixer *m = Engine::fxMixer();
|
||||
|
||||
FxMixer * mix = Engine::fxMixer();
|
||||
mix->moveChannelLeft(index);
|
||||
// Move instruments channels
|
||||
m->moveChannelLeft( index );
|
||||
|
||||
// refresh the two mixer views
|
||||
for( int i = index-1; i <= index; ++i )
|
||||
{
|
||||
// delete the mixer view
|
||||
int replaceIndex = chLayout->indexOf(m_fxChannelViews[i]->m_fxLine);
|
||||
// Update widgets models
|
||||
m_fxChannelViews[index]->setChannelIndex( index - 1 );
|
||||
m_fxChannelViews[index - 1]->setChannelIndex( index );
|
||||
|
||||
chLayout->removeWidget(m_fxChannelViews[i]->m_fxLine);
|
||||
m_racksLayout->removeWidget( m_fxChannelViews[i]->m_rackView );
|
||||
delete m_fxChannelViews[i]->m_fader;
|
||||
delete m_fxChannelViews[i]->m_muteBtn;
|
||||
delete m_fxChannelViews[i]->m_soloBtn;
|
||||
delete m_fxChannelViews[i]->m_fxLine;
|
||||
delete m_fxChannelViews[i];
|
||||
// Swap positions in array
|
||||
qSwap(m->m_fxChannels[index], m->m_fxChannels[index - 1]);
|
||||
|
||||
// add it again
|
||||
m_fxChannelViews[i] = new FxChannelView( m_channelAreaWidget, this, i );
|
||||
chLayout->insertWidget( replaceIndex, m_fxChannelViews[i]->m_fxLine );
|
||||
m_racksLayout->insertWidget( replaceIndex, m_fxChannelViews[i]->m_rackView );
|
||||
}
|
||||
// Focus on new position
|
||||
setCurrentFxLine( focusIndex );
|
||||
}
|
||||
|
||||
// keep selected channel
|
||||
if( selIndex == index )
|
||||
{
|
||||
selIndex = index-1;
|
||||
}
|
||||
else if( selIndex == index - 1 )
|
||||
{
|
||||
selIndex = index;
|
||||
}
|
||||
setCurrentFxLine(selIndex);
|
||||
|
||||
|
||||
void FxMixerView::moveChannelLeft(int index)
|
||||
{
|
||||
moveChannelLeft( index, index - 1 );
|
||||
}
|
||||
|
||||
|
||||
|
||||
void FxMixerView::moveChannelRight(int index)
|
||||
{
|
||||
moveChannelLeft(index+1);
|
||||
moveChannelLeft( index + 1, index + 1 );
|
||||
}
|
||||
|
||||
|
||||
@@ -512,6 +510,12 @@ void FxMixerView::keyPressEvent(QKeyEvent * e)
|
||||
setCurrentFxLine( m_currentFxLine->channelIndex()+1 );
|
||||
}
|
||||
break;
|
||||
case Qt::Key_Insert:
|
||||
if ( e->modifiers() & Qt::ShiftModifier )
|
||||
{
|
||||
addNewChannel();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -49,6 +49,7 @@ GuiApplication* GuiApplication::instance()
|
||||
return s_instance;
|
||||
}
|
||||
|
||||
|
||||
GuiApplication::GuiApplication()
|
||||
{
|
||||
// Init style and palette
|
||||
@@ -64,27 +65,60 @@ GuiApplication::GuiApplication()
|
||||
// Show splash screen
|
||||
QSplashScreen splashScreen( embed::getIconPixmap( "splash" ) );
|
||||
splashScreen.show();
|
||||
splashScreen.showMessage( MainWindow::tr( "Version %1" ).arg( LMMS_VERSION ),
|
||||
Qt::AlignRight | Qt::AlignBottom, Qt::white );
|
||||
|
||||
QHBoxLayout layout;
|
||||
layout.setAlignment(Qt::AlignBottom);
|
||||
splashScreen.setLayout(&layout);
|
||||
|
||||
// Create a left-aligned label for loading progress
|
||||
// & a right-aligned label for version info
|
||||
QLabel loadingProgressLabel;
|
||||
m_loadingProgressLabel = &loadingProgressLabel;
|
||||
QLabel versionLabel(MainWindow::tr( "Version %1" ).arg( LMMS_VERSION ));
|
||||
|
||||
loadingProgressLabel.setAlignment(Qt::AlignLeft);
|
||||
versionLabel.setAlignment(Qt::AlignRight);
|
||||
|
||||
layout.addWidget(&loadingProgressLabel);
|
||||
layout.addWidget(&versionLabel);
|
||||
|
||||
// may have long gaps between future frames, so force update now
|
||||
splashScreen.update();
|
||||
qApp->processEvents();
|
||||
|
||||
connect(Engine::inst(), SIGNAL(initProgress(const QString&)),
|
||||
this, SLOT(displayInitProgress(const QString&)));
|
||||
|
||||
// Init central engine which handles all components of LMMS
|
||||
Engine::init();
|
||||
|
||||
s_instance = this;
|
||||
|
||||
m_mainWindow = new MainWindow;
|
||||
displayInitProgress(tr("Preparing UI"));
|
||||
|
||||
m_mainWindow = new MainWindow;
|
||||
connect(m_mainWindow, SIGNAL(initProgress(const QString&)),
|
||||
this, SLOT(displayInitProgress(const QString&)));
|
||||
|
||||
displayInitProgress(tr("Preparing song editor"));
|
||||
m_songEditor = new SongEditorWindow(Engine::getSong());
|
||||
displayInitProgress(tr("Preparing mixer"));
|
||||
m_fxMixerView = new FxMixerView;
|
||||
displayInitProgress(tr("Preparing controller rack"));
|
||||
m_controllerRackView = new ControllerRackView;
|
||||
displayInitProgress(tr("Preparing project notes"));
|
||||
m_projectNotes = new ProjectNotes;
|
||||
displayInitProgress(tr("Preparing beat/bassline editor"));
|
||||
m_bbEditor = new BBEditor(Engine::getBBTrackContainer());
|
||||
displayInitProgress(tr("Preparing piano roll"));
|
||||
m_pianoRoll = new PianoRollWindow();
|
||||
displayInitProgress(tr("Preparing automation editor"));
|
||||
m_automationEditor = new AutomationEditorWindow;
|
||||
|
||||
m_mainWindow->finalize();
|
||||
splashScreen.finish(m_mainWindow);
|
||||
|
||||
m_loadingProgressLabel = nullptr;
|
||||
}
|
||||
|
||||
GuiApplication::~GuiApplication()
|
||||
@@ -92,3 +126,14 @@ GuiApplication::~GuiApplication()
|
||||
InstrumentTrackView::cleanupWindowCache();
|
||||
s_instance = nullptr;
|
||||
}
|
||||
|
||||
|
||||
void GuiApplication::displayInitProgress(const QString &msg)
|
||||
{
|
||||
Q_ASSERT(m_loadingProgressLabel != nullptr);
|
||||
|
||||
m_loadingProgressLabel->setText(msg);
|
||||
// must force a UI update and process events, as there may be long gaps between processEvents() calls during init
|
||||
m_loadingProgressLabel->repaint();
|
||||
qApp->processEvents();
|
||||
}
|
||||
|
||||
@@ -50,7 +50,6 @@ const int CD_KNOB_X_SPACING = 32;
|
||||
const int CD_LFO_SHAPES_X = 6;
|
||||
const int CD_LFO_SHAPES_Y = 36;
|
||||
|
||||
const int CD_LFO_GRAPH_X = 6;
|
||||
const int CD_LFO_GRAPH_Y = CD_ENV_KNOBS_LBL_Y+15;
|
||||
const int CD_LFO_CD_KNOB_Y = CD_LFO_GRAPH_Y-2;
|
||||
const int CD_LFO_BASE_CD_KNOB_X = CD_LFO_SHAPES_X + 64;
|
||||
@@ -243,7 +242,6 @@ LfoControllerDialog::LfoControllerDialog( Controller * _model, QWidget * _parent
|
||||
LfoControllerDialog::~LfoControllerDialog()
|
||||
{
|
||||
m_userWaveBtn->disconnect( this );
|
||||
//delete m_subWindow;
|
||||
}
|
||||
|
||||
|
||||
@@ -287,13 +285,6 @@ void LfoControllerDialog::contextMenuEvent( QContextMenuEvent * )
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
void lfoControllerDialog::paintEvent( QPaintEvent * _pe )
|
||||
{
|
||||
QWidget::paintEvent( _pe );
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
void LfoControllerDialog::modelChanged()
|
||||
{
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
#include <QMdiSubWindow>
|
||||
#include <QMenuBar>
|
||||
#include <QMessageBox>
|
||||
#include <QShortcut>
|
||||
#include <QSplitter>
|
||||
#include <QWhatsThis>
|
||||
|
||||
@@ -97,7 +98,9 @@ MainWindow::MainWindow() :
|
||||
|
||||
ConfigManager* confMgr = ConfigManager::inst();
|
||||
|
||||
emit initProgress(tr("Preparing plugin browser"));
|
||||
sideBar->appendTab( new PluginBrowser( splitter ) );
|
||||
emit initProgress(tr("Preparing file browsers"));
|
||||
sideBar->appendTab( new FileBrowser(
|
||||
confMgr->userProjectsDir() + "*" +
|
||||
confMgr->factoryProjectsDir(),
|
||||
@@ -151,6 +154,7 @@ MainWindow::MainWindow() :
|
||||
m_workspace = new QMdiArea( splitter );
|
||||
|
||||
// Load background
|
||||
emit initProgress(tr("Loading background artwork"));
|
||||
QString bgArtwork = ConfigManager::inst()->backgroundArtwork();
|
||||
QImage bgImage;
|
||||
if( !bgArtwork.isEmpty() )
|
||||
@@ -232,12 +236,12 @@ void MainWindow::finalize()
|
||||
project_menu->addAction( embed::getIconPixmap( "project_new" ),
|
||||
tr( "&New" ),
|
||||
this, SLOT( createNewProject() ),
|
||||
Qt::CTRL + Qt::Key_N );
|
||||
QKeySequence::New );
|
||||
|
||||
project_menu->addAction( embed::getIconPixmap( "project_open" ),
|
||||
tr( "&Open..." ),
|
||||
this, SLOT( openProject() ),
|
||||
Qt::CTRL + Qt::Key_O );
|
||||
QKeySequence::Open );
|
||||
|
||||
m_recentlyOpenedProjectsMenu = project_menu->addMenu(
|
||||
embed::getIconPixmap( "project_open_recent" ),
|
||||
@@ -250,7 +254,7 @@ void MainWindow::finalize()
|
||||
project_menu->addAction( embed::getIconPixmap( "project_save" ),
|
||||
tr( "&Save" ),
|
||||
this, SLOT( saveProject() ),
|
||||
Qt::CTRL + Qt::Key_S );
|
||||
QKeySequence::Save );
|
||||
project_menu->addAction( embed::getIconPixmap( "project_saveas" ),
|
||||
tr( "Save &As..." ),
|
||||
this, SLOT( saveProjectAs() ),
|
||||
@@ -289,18 +293,29 @@ void MainWindow::finalize()
|
||||
|
||||
QMenu * edit_menu = new QMenu( this );
|
||||
menuBar()->addMenu( edit_menu )->setText( tr( "&Edit" ) );
|
||||
edit_menu->addAction( embed::getIconPixmap( "edit_undo" ),
|
||||
m_undoAction = edit_menu->addAction( embed::getIconPixmap( "edit_undo" ),
|
||||
tr( "Undo" ),
|
||||
this, SLOT( undo() ),
|
||||
Qt::CTRL + Qt::Key_Z );
|
||||
edit_menu->addAction( embed::getIconPixmap( "edit_redo" ),
|
||||
QKeySequence::Undo );
|
||||
m_redoAction = edit_menu->addAction( embed::getIconPixmap( "edit_redo" ),
|
||||
tr( "Redo" ),
|
||||
this, SLOT( redo() ),
|
||||
Qt::CTRL + Qt::Key_Y );
|
||||
QKeySequence::Redo );
|
||||
// Ensure that both (Ctrl+Y) and (Ctrl+Shift+Z) activate redo shortcut regardless of OS defaults
|
||||
if (QKeySequence(QKeySequence::Redo) != QKeySequence(Qt::CTRL + Qt::Key_Y))
|
||||
{
|
||||
new QShortcut( QKeySequence( Qt::CTRL + Qt::Key_Y ), this, SLOT(redo()) );
|
||||
}
|
||||
if (QKeySequence(QKeySequence::Redo) != QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_Z ))
|
||||
{
|
||||
new QShortcut( QKeySequence( Qt::CTRL + Qt::SHIFT + Qt::Key_Z ), this, SLOT(redo()) );
|
||||
}
|
||||
|
||||
edit_menu->addSeparator();
|
||||
edit_menu->addAction( embed::getIconPixmap( "setup_general" ),
|
||||
tr( "Settings" ),
|
||||
this, SLOT( showSettingsDialog() ) );
|
||||
connect( edit_menu, SIGNAL(aboutToShow()), this, SLOT(updateUndoRedoButtons()) );
|
||||
|
||||
m_viewMenu = new QMenu( this );
|
||||
menuBar()->addMenu( m_viewMenu )->setText( tr( "&View" ) );
|
||||
@@ -379,7 +394,7 @@ void MainWindow::finalize()
|
||||
|
||||
ToolButton * project_open_recent = new ToolButton(
|
||||
embed::getIconPixmap( "project_open_recent" ),
|
||||
tr( "Recently opened project" ),
|
||||
tr( "Recently opened projects" ),
|
||||
this, SLOT( emptySlot() ), m_toolBar );
|
||||
project_open_recent->setMenu( m_recentlyOpenedProjectsMenu );
|
||||
project_open_recent->setPopupMode( ToolButton::InstantPopup );
|
||||
@@ -732,6 +747,14 @@ void MainWindow::createNewProject()
|
||||
{
|
||||
Engine::getSong()->createNewProject();
|
||||
}
|
||||
QString default_template = ConfigManager::inst()->userTemplateDir()
|
||||
+ "default.mpt";
|
||||
|
||||
//if we dont have a user default template, make one
|
||||
if( !QFile::exists( default_template ) )
|
||||
{
|
||||
Engine::getSong()->saveProjectFile( default_template );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1059,35 +1082,37 @@ void MainWindow::updateViewMenu()
|
||||
qa = new QAction(tr( "Volume as dBV" ), this);
|
||||
qa->setData("displaydbv");
|
||||
qa->setCheckable( true );
|
||||
qa->setChecked( ConfigManager::inst()->value( "app", "displaydbv" ).
|
||||
toInt() ? true : false );
|
||||
qa->setChecked( ConfigManager::inst()->value( "app", "displaydbv" ).toInt() );
|
||||
m_viewMenu->addAction(qa);
|
||||
|
||||
// Maybe this is impossible?
|
||||
/* qa = new QAction(tr( "Tooltips" ), this);
|
||||
qa->setData("tooltips");
|
||||
qa->setCheckable( true );
|
||||
qa->setChecked( ConfigManager::inst()->value( "tooltips", "disabled" ).
|
||||
toInt() ? false : true );
|
||||
qa->setChecked( !ConfigManager::inst()->value( "tooltips", "disabled" ).toInt() );
|
||||
m_viewMenu->addAction(qa);
|
||||
*/
|
||||
|
||||
// Should be doable.
|
||||
qa = new QAction(tr( "Smooth scroll" ), this);
|
||||
qa->setData("smoothscroll");
|
||||
qa->setCheckable( true );
|
||||
qa->setChecked( ConfigManager::inst()->value( "ui", "smoothscroll" ).
|
||||
toInt() ? true : false );
|
||||
qa->setChecked( ConfigManager::inst()->value( "ui", "smoothscroll" ).toInt() );
|
||||
m_viewMenu->addAction(qa);
|
||||
|
||||
// Not yet.
|
||||
/* qa = new QAction(tr( "One instrument track window" ), this);
|
||||
qa->setData("oneinstrument");
|
||||
qa->setCheckable( true );
|
||||
qa->setChecked( ConfigManager::inst()->value( "ui", "oneinstrumenttrackwindow" ).
|
||||
toInt() ? true : false );
|
||||
qa->setChecked( ConfigManager::inst()->value( "ui", "oneinstrumenttrackwindow" ).toInt() );
|
||||
m_viewMenu->addAction(qa);
|
||||
*/
|
||||
|
||||
qa = new QAction(tr( "Enable note labels in piano roll" ), this);
|
||||
qa->setData("printnotelabels");
|
||||
qa->setCheckable( true );
|
||||
qa->setChecked( ConfigManager::inst()->value( "ui", "printnotelabels" ).toInt() );
|
||||
m_viewMenu->addAction(qa);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -1116,6 +1141,11 @@ void MainWindow::updateConfig( QAction * _who )
|
||||
ConfigManager::inst()->setValue( "ui", "oneinstrumenttrackwindow",
|
||||
QString::number(checked) );
|
||||
}
|
||||
else if ( tag == "printnotelabels" )
|
||||
{
|
||||
ConfigManager::inst()->setValue( "ui", "printnotelabels",
|
||||
QString::number(checked) );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1161,6 +1191,14 @@ void MainWindow::updatePlayPauseIcons()
|
||||
}
|
||||
|
||||
|
||||
void MainWindow::updateUndoRedoButtons()
|
||||
{
|
||||
// when the edit menu is shown, grey out the undo/redo buttons if there's nothing to undo/redo
|
||||
// else, un-grey them
|
||||
m_undoAction->setEnabled(Engine::projectJournal()->canUndo());
|
||||
m_redoAction->setEnabled(Engine::projectJournal()->canRedo());
|
||||
}
|
||||
|
||||
|
||||
|
||||
void MainWindow::undo()
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
#include <QMessageBox>
|
||||
#include <QSlider>
|
||||
#include <QWhatsThis>
|
||||
#include <QScrollArea>
|
||||
|
||||
#include "SetupDialog.h"
|
||||
#include "TabBar.h"
|
||||
@@ -105,6 +106,8 @@ SetupDialog::SetupDialog( ConfigTabs _tab_to_open ) :
|
||||
m_artworkDir( QDir::toNativeSeparators( ConfigManager::inst()->artworkDir() ) ),
|
||||
m_flDir( QDir::toNativeSeparators( ConfigManager::inst()->flDir() ) ),
|
||||
m_ladDir( QDir::toNativeSeparators( ConfigManager::inst()->ladspaDir() ) ),
|
||||
m_gigDir( QDir::toNativeSeparators( ConfigManager::inst()->gigDir() ) ),
|
||||
m_sf2Dir( QDir::toNativeSeparators( ConfigManager::inst()->sf2Dir() ) ),
|
||||
#ifdef LMMS_HAVE_FLUIDSYNTH
|
||||
m_defaultSoundfont( QDir::toNativeSeparators( ConfigManager::inst()->defaultSoundfont() ) ),
|
||||
#endif
|
||||
@@ -378,15 +381,34 @@ SetupDialog::SetupDialog( ConfigTabs _tab_to_open ) :
|
||||
dir_layout->setSpacing( 0 );
|
||||
dir_layout->setMargin( 0 );
|
||||
labelWidget( paths, tr( "Paths" ) );
|
||||
QLabel * title = new QLabel( tr( "Directories" ), paths );
|
||||
QFont f = title->font();
|
||||
f.setBold( true );
|
||||
title->setFont( pointSize<12>( f ) );
|
||||
|
||||
|
||||
QScrollArea *pathScroll = new QScrollArea( paths );
|
||||
|
||||
QWidget *pathSelectors = new QWidget( ws );
|
||||
QVBoxLayout *pathSelectorLayout = new QVBoxLayout;
|
||||
pathScroll->setVerticalScrollBarPolicy( Qt::ScrollBarAlwaysOn );
|
||||
pathScroll->setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
|
||||
pathScroll->resize( 362, pathsHeight - 50 );
|
||||
pathScroll->move( 0, 30 );
|
||||
pathSelectors->resize( 360, pathsHeight - 50 );
|
||||
|
||||
const int txtLength = 285;
|
||||
const int btnStart = 305;
|
||||
|
||||
|
||||
// working-dir
|
||||
TabWidget * lmms_wd_tw = new TabWidget( tr(
|
||||
"LMMS working directory" ).toUpper(),
|
||||
paths );
|
||||
pathSelectors );
|
||||
lmms_wd_tw->setFixedHeight( 48 );
|
||||
|
||||
m_wdLineEdit = new QLineEdit( m_workingDir, lmms_wd_tw );
|
||||
m_wdLineEdit->setGeometry( 10, 20, 300, 16 );
|
||||
m_wdLineEdit->setGeometry( 10, 20, txtLength, 16 );
|
||||
connect( m_wdLineEdit, SIGNAL( textChanged( const QString & ) ), this,
|
||||
SLOT( setWorkingDir( const QString & ) ) );
|
||||
|
||||
@@ -394,37 +416,19 @@ SetupDialog::SetupDialog( ConfigTabs _tab_to_open ) :
|
||||
embed::getIconPixmap( "project_open", 16, 16 ),
|
||||
"", lmms_wd_tw );
|
||||
workingdir_select_btn->setFixedSize( 24, 24 );
|
||||
workingdir_select_btn->move( 320, 16 );
|
||||
workingdir_select_btn->move( btnStart, 16 );
|
||||
connect( workingdir_select_btn, SIGNAL( clicked() ), this,
|
||||
SLOT( openWorkingDir() ) );
|
||||
|
||||
// vst-dir
|
||||
TabWidget * vst_tw = new TabWidget( tr(
|
||||
"VST-plugin directory" ).toUpper(),
|
||||
paths );
|
||||
vst_tw->setFixedHeight( 48 );
|
||||
|
||||
m_vdLineEdit = new QLineEdit( m_vstDir, vst_tw );
|
||||
m_vdLineEdit->setGeometry( 10, 20, 300, 16 );
|
||||
connect( m_vdLineEdit, SIGNAL( textChanged( const QString & ) ), this,
|
||||
SLOT( setVSTDir( const QString & ) ) );
|
||||
|
||||
QPushButton * vstdir_select_btn = new QPushButton(
|
||||
embed::getIconPixmap( "project_open", 16, 16 ),
|
||||
"", vst_tw );
|
||||
vstdir_select_btn->setFixedSize( 24, 24 );
|
||||
vstdir_select_btn->move( 320, 16 );
|
||||
connect( vstdir_select_btn, SIGNAL( clicked() ), this,
|
||||
SLOT( openVSTDir() ) );
|
||||
|
||||
// artwork-dir
|
||||
TabWidget * artwork_tw = new TabWidget( tr(
|
||||
"Artwork directory" ).toUpper(),
|
||||
paths );
|
||||
"Themes directory" ).toUpper(),
|
||||
pathSelectors );
|
||||
artwork_tw->setFixedHeight( 48 );
|
||||
|
||||
m_adLineEdit = new QLineEdit( m_artworkDir, artwork_tw );
|
||||
m_adLineEdit->setGeometry( 10, 20, 300, 16 );
|
||||
m_adLineEdit->setGeometry( 10, 20, txtLength, 16 );
|
||||
connect( m_adLineEdit, SIGNAL( textChanged( const QString & ) ), this,
|
||||
SLOT( setArtworkDir( const QString & ) ) );
|
||||
|
||||
@@ -432,7 +436,7 @@ SetupDialog::SetupDialog( ConfigTabs _tab_to_open ) :
|
||||
embed::getIconPixmap( "project_open", 16, 16 ),
|
||||
"", artwork_tw );
|
||||
artworkdir_select_btn->setFixedSize( 24, 24 );
|
||||
artworkdir_select_btn->move( 320, 16 );
|
||||
artworkdir_select_btn->move( btnStart, 16 );
|
||||
connect( artworkdir_select_btn, SIGNAL( clicked() ), this,
|
||||
SLOT( openArtworkDir() ) );
|
||||
|
||||
@@ -445,7 +449,7 @@ SetupDialog::SetupDialog( ConfigTabs _tab_to_open ) :
|
||||
|
||||
m_baLineEdit = new QLineEdit( m_backgroundArtwork,
|
||||
backgroundArtwork_tw );
|
||||
m_baLineEdit->setGeometry( 10, 20, 300, 16 );
|
||||
m_baLineEdit->setGeometry( 10, 20, txtLength, 16 );
|
||||
connect( m_baLineEdit, SIGNAL( textChanged( const QString & ) ), this,
|
||||
SLOT( setBackgroundArtwork( const QString & ) ) );
|
||||
|
||||
@@ -453,7 +457,7 @@ SetupDialog::SetupDialog( ConfigTabs _tab_to_open ) :
|
||||
embed::getIconPixmap( "project_open", 16, 16 ),
|
||||
"", backgroundArtwork_tw );
|
||||
backgroundartworkdir_select_btn->setFixedSize( 24, 24 );
|
||||
backgroundartworkdir_select_btn->move( 320, 16 );
|
||||
backgroundartworkdir_select_btn->move( btnStart, 16 );
|
||||
connect( backgroundartworkdir_select_btn, SIGNAL( clicked() ), this,
|
||||
SLOT( openBackgroundArtwork() ) );
|
||||
|
||||
@@ -468,7 +472,7 @@ SetupDialog::SetupDialog( ConfigTabs _tab_to_open ) :
|
||||
fl_tw->setFixedHeight( 48 );
|
||||
|
||||
m_fdLineEdit = new QLineEdit( m_flDir, fl_tw );
|
||||
m_fdLineEdit->setGeometry( 10, 20, 300, 16 );
|
||||
m_fdLineEdit->setGeometry( 10, 20, txtLength, 16 );
|
||||
connect( m_fdLineEdit, SIGNAL( textChanged( const QString & ) ), this,
|
||||
SLOT( setFLDir( const QString & ) ) );
|
||||
|
||||
@@ -476,28 +480,89 @@ SetupDialog::SetupDialog( ConfigTabs _tab_to_open ) :
|
||||
embed::getIconPixmap( "project_open", 16, 16 ),
|
||||
"", fl_tw );
|
||||
fldir_select_btn->setFixedSize( 24, 24 );
|
||||
fldir_select_btn->move( 320, 16 );
|
||||
fldir_select_btn->move( btnStart, 16 );
|
||||
connect( fldir_select_btn, SIGNAL( clicked() ), this,
|
||||
SLOT( openFLDir() ) );
|
||||
|
||||
// vst-dir
|
||||
TabWidget * vst_tw = new TabWidget( tr(
|
||||
"VST-plugin directory" ).toUpper(),
|
||||
pathSelectors );
|
||||
vst_tw->setFixedHeight( 48 );
|
||||
|
||||
m_vdLineEdit = new QLineEdit( m_vstDir, vst_tw );
|
||||
m_vdLineEdit->setGeometry( 10, 20, txtLength, 16 );
|
||||
connect( m_vdLineEdit, SIGNAL( textChanged( const QString & ) ), this,
|
||||
SLOT( setVSTDir( const QString & ) ) );
|
||||
|
||||
QPushButton * vstdir_select_btn = new QPushButton(
|
||||
embed::getIconPixmap( "project_open", 16, 16 ),
|
||||
"", vst_tw );
|
||||
vstdir_select_btn->setFixedSize( 24, 24 );
|
||||
vstdir_select_btn->move( btnStart, 16 );
|
||||
connect( vstdir_select_btn, SIGNAL( clicked() ), this,
|
||||
SLOT( openVSTDir() ) );
|
||||
|
||||
// gig-dir
|
||||
TabWidget * gig_tw = new TabWidget( tr(
|
||||
"GIG directory" ).toUpper(),
|
||||
pathSelectors );
|
||||
gig_tw->setFixedHeight( 48 );
|
||||
|
||||
m_gigLineEdit = new QLineEdit( m_gigDir, gig_tw );
|
||||
m_gigLineEdit->setGeometry( 10, 20, txtLength, 16 );
|
||||
connect( m_gigLineEdit, SIGNAL( textChanged( const QString & ) ), this,
|
||||
SLOT( setGIGDir( const QString & ) ) );
|
||||
|
||||
QPushButton * gigdir_select_btn = new QPushButton(
|
||||
embed::getIconPixmap( "project_open", 16, 16 ),
|
||||
"", gig_tw );
|
||||
gigdir_select_btn->setFixedSize( 24, 24 );
|
||||
gigdir_select_btn->move( btnStart, 16 );
|
||||
connect( gigdir_select_btn, SIGNAL( clicked() ), this,
|
||||
SLOT( openGIGDir() ) );
|
||||
|
||||
// sf2-dir
|
||||
TabWidget * sf2_tw = new TabWidget( tr(
|
||||
"SF2 directory" ).toUpper(),
|
||||
pathSelectors );
|
||||
sf2_tw->setFixedHeight( 48 );
|
||||
|
||||
m_sf2LineEdit = new QLineEdit( m_sf2Dir, sf2_tw );
|
||||
m_sf2LineEdit->setGeometry( 10, 20, txtLength, 16 );
|
||||
connect( m_sf2LineEdit, SIGNAL( textChanged( const QString & ) ), this,
|
||||
SLOT( setSF2Dir( const QString & ) ) );
|
||||
|
||||
QPushButton * sf2dir_select_btn = new QPushButton(
|
||||
embed::getIconPixmap( "project_open", 16, 16 ),
|
||||
"", sf2_tw );
|
||||
sf2dir_select_btn->setFixedSize( 24, 24 );
|
||||
sf2dir_select_btn->move( btnStart, 16 );
|
||||
connect( sf2dir_select_btn, SIGNAL( clicked() ), this,
|
||||
SLOT( openSF2Dir() ) );
|
||||
|
||||
|
||||
|
||||
// LADSPA-dir
|
||||
TabWidget * lad_tw = new TabWidget( tr(
|
||||
"LADSPA plugin paths" ).toUpper(),
|
||||
"LADSPA plugin directories" ).toUpper(),
|
||||
paths );
|
||||
lad_tw->setFixedHeight( 48 );
|
||||
|
||||
m_ladLineEdit = new QLineEdit( m_ladDir, lad_tw );
|
||||
m_ladLineEdit->setGeometry( 10, 20, 300, 16 );
|
||||
m_ladLineEdit->setGeometry( 10, 20, txtLength, 16 );
|
||||
connect( m_ladLineEdit, SIGNAL( textChanged( const QString & ) ), this,
|
||||
SLOT( setLADSPADir( const QString & ) ) );
|
||||
|
||||
QPushButton * laddir_select_btn = new QPushButton(
|
||||
embed::getIconPixmap( "project_open", 16, 16 ),
|
||||
embed::getIconPixmap( "add_folder", 16, 16 ),
|
||||
"", lad_tw );
|
||||
laddir_select_btn->setFixedSize( 24, 24 );
|
||||
laddir_select_btn->move( 320, 16 );
|
||||
laddir_select_btn->move( btnStart, 16 );
|
||||
connect( laddir_select_btn, SIGNAL( clicked() ), this,
|
||||
SLOT( openLADSPADir() ) );
|
||||
|
||||
|
||||
#ifdef LMMS_HAVE_STK
|
||||
// STK-dir
|
||||
TabWidget * stk_tw = new TabWidget( tr(
|
||||
@@ -506,7 +571,7 @@ SetupDialog::SetupDialog( ConfigTabs _tab_to_open ) :
|
||||
stk_tw->setFixedHeight( 48 );
|
||||
|
||||
m_stkLineEdit = new QLineEdit( m_stkDir, stk_tw );
|
||||
m_stkLineEdit->setGeometry( 10, 20, 300, 16 );
|
||||
m_stkLineEdit->setGeometry( 10, 20, txtLength, 16 );
|
||||
connect( m_stkLineEdit, SIGNAL( textChanged( const QString & ) ), this,
|
||||
SLOT( setSTKDir( const QString & ) ) );
|
||||
|
||||
@@ -514,7 +579,7 @@ SetupDialog::SetupDialog( ConfigTabs _tab_to_open ) :
|
||||
embed::getIconPixmap( "project_open", 16, 16 ),
|
||||
"", stk_tw );
|
||||
stkdir_select_btn->setFixedSize( 24, 24 );
|
||||
stkdir_select_btn->move( 320, 16 );
|
||||
stkdir_select_btn->move( btnStart, 16 );
|
||||
connect( stkdir_select_btn, SIGNAL( clicked() ), this,
|
||||
SLOT( openSTKDir() ) );
|
||||
#endif
|
||||
@@ -526,7 +591,7 @@ SetupDialog::SetupDialog( ConfigTabs _tab_to_open ) :
|
||||
sf_tw->setFixedHeight( 48 );
|
||||
|
||||
m_sfLineEdit = new QLineEdit( m_defaultSoundfont, sf_tw );
|
||||
m_sfLineEdit->setGeometry( 10, 20, 300, 16 );
|
||||
m_sfLineEdit->setGeometry( 10, 20, txtLength, 16 );
|
||||
connect( m_sfLineEdit, SIGNAL( textChanged( const QString & ) ), this,
|
||||
SLOT( setDefaultSoundfont( const QString & ) ) );
|
||||
|
||||
@@ -534,34 +599,42 @@ SetupDialog::SetupDialog( ConfigTabs _tab_to_open ) :
|
||||
embed::getIconPixmap( "project_open", 16, 16 ),
|
||||
"", sf_tw );
|
||||
sf_select_btn->setFixedSize( 24, 24 );
|
||||
sf_select_btn->move( 320, 16 );
|
||||
sf_select_btn->move( btnStart, 16 );
|
||||
connect( sf_select_btn, SIGNAL( clicked() ), this,
|
||||
SLOT( openDefaultSoundfont() ) );
|
||||
#endif
|
||||
|
||||
pathSelectors->setLayout( pathSelectorLayout );
|
||||
|
||||
dir_layout->addWidget( lmms_wd_tw );
|
||||
dir_layout->addSpacing( 10 );
|
||||
dir_layout->addWidget( vst_tw );
|
||||
dir_layout->addSpacing( 10 );
|
||||
dir_layout->addWidget( artwork_tw );
|
||||
dir_layout->addSpacing( 10 );
|
||||
dir_layout->addWidget( backgroundArtwork_tw );
|
||||
dir_layout->addSpacing( 10 );
|
||||
dir_layout->addWidget( fl_tw );
|
||||
dir_layout->addSpacing( 10 );
|
||||
dir_layout->addWidget( lad_tw );
|
||||
pathSelectorLayout->addWidget( lmms_wd_tw );
|
||||
pathSelectorLayout->addSpacing( 10 );
|
||||
pathSelectorLayout->addWidget( gig_tw );
|
||||
pathSelectorLayout->addSpacing( 10 );
|
||||
pathSelectorLayout->addWidget( sf2_tw );
|
||||
pathSelectorLayout->addSpacing( 10 );
|
||||
pathSelectorLayout->addWidget( vst_tw );
|
||||
pathSelectorLayout->addSpacing( 10 );
|
||||
pathSelectorLayout->addWidget( lad_tw );
|
||||
#ifdef LMMS_HAVE_STK
|
||||
dir_layout->addSpacing( 10 );
|
||||
dir_layout->addWidget( stk_tw );
|
||||
pathSelectorLayout->addSpacing( 10 );
|
||||
pathSelectorLayout->addWidget( stk_tw );
|
||||
#endif
|
||||
#ifdef LMMS_HAVE_FLUIDSYNTH
|
||||
dir_layout->addSpacing( 10 );
|
||||
dir_layout->addWidget( sf_tw );
|
||||
pathSelectorLayout->addSpacing( 10 );
|
||||
pathSelectorLayout->addWidget( sf_tw );
|
||||
#endif
|
||||
dir_layout->addStretch();
|
||||
pathSelectorLayout->addWidget( fl_tw );
|
||||
pathSelectorLayout->addSpacing( 10 );
|
||||
pathSelectorLayout->addWidget( artwork_tw );
|
||||
pathSelectorLayout->addSpacing( 10 );
|
||||
pathSelectorLayout->addStretch();
|
||||
pathSelectorLayout->addWidget( backgroundArtwork_tw );
|
||||
pathSelectorLayout->addSpacing( 10 );
|
||||
|
||||
dir_layout->addWidget( pathSelectors );
|
||||
|
||||
pathScroll->setWidget( pathSelectors );
|
||||
pathScroll->setWidgetResizable( true );
|
||||
|
||||
|
||||
|
||||
@@ -905,6 +978,8 @@ void SetupDialog::accept()
|
||||
|
||||
ConfigManager::inst()->setWorkingDir( m_workingDir );
|
||||
ConfigManager::inst()->setVSTDir( m_vstDir );
|
||||
ConfigManager::inst()->setGIGDir( m_gigDir );
|
||||
ConfigManager::inst()->setSF2Dir( m_sf2Dir );
|
||||
ConfigManager::inst()->setArtworkDir( m_artworkDir );
|
||||
ConfigManager::inst()->setFLDir( m_flDir );
|
||||
ConfigManager::inst()->setLADSPADir( m_ladDir );
|
||||
@@ -1128,6 +1203,28 @@ void SetupDialog::openWorkingDir()
|
||||
}
|
||||
}
|
||||
|
||||
void SetupDialog::openGIGDir()
|
||||
{
|
||||
QString new_dir = FileDialog::getExistingDirectory( this,
|
||||
tr( "Choose your GIG directory" ),
|
||||
m_gigDir );
|
||||
if( new_dir != QString::null )
|
||||
{
|
||||
m_gigLineEdit->setText( new_dir );
|
||||
}
|
||||
}
|
||||
|
||||
void SetupDialog::openSF2Dir()
|
||||
{
|
||||
QString new_dir = FileDialog::getExistingDirectory( this,
|
||||
tr( "Choose your SF2 directory" ),
|
||||
m_sf2Dir );
|
||||
if( new_dir != QString::null )
|
||||
{
|
||||
m_sf2LineEdit->setText( new_dir );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1158,6 +1255,16 @@ void SetupDialog::setVSTDir( const QString & _vd )
|
||||
m_vstDir = _vd;
|
||||
}
|
||||
|
||||
void SetupDialog::setGIGDir(const QString &_gd)
|
||||
{
|
||||
m_gigDir = _gd;
|
||||
}
|
||||
|
||||
void SetupDialog::setSF2Dir(const QString &_sfd)
|
||||
{
|
||||
m_sf2Dir = _sfd;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1218,7 +1325,6 @@ void SetupDialog::openLADSPADir()
|
||||
|
||||
|
||||
|
||||
|
||||
void SetupDialog::openSTKDir()
|
||||
{
|
||||
#ifdef LMMS_HAVE_STK
|
||||
|
||||
@@ -52,7 +52,7 @@ StringPairDrag::StringPairDrag( const QString & _key, const QString & _value,
|
||||
}
|
||||
QString txt = _key + ":" + _value;
|
||||
QMimeData * m = new QMimeData();
|
||||
m->setData( mimeType(), txt.toLatin1() );
|
||||
m->setData( mimeType(), txt.toUtf8() );
|
||||
setMimeData( m );
|
||||
start( Qt::IgnoreAction );
|
||||
}
|
||||
@@ -95,7 +95,7 @@ bool StringPairDrag::processDragEnterEvent( QDragEnterEvent * _dee,
|
||||
|
||||
QString StringPairDrag::decodeMimeKey( const QMimeData * mimeData )
|
||||
{
|
||||
return( QString( mimeData->data( mimeType() ) ).section( ':', 0, 0 ) );
|
||||
return( QString::fromUtf8( mimeData->data( mimeType() ) ).section( ':', 0, 0 ) );
|
||||
}
|
||||
|
||||
|
||||
@@ -103,7 +103,7 @@ QString StringPairDrag::decodeMimeKey( const QMimeData * mimeData )
|
||||
|
||||
QString StringPairDrag::decodeMimeValue( const QMimeData * mimeData )
|
||||
{
|
||||
return( QString( mimeData->data( mimeType() ) ).section( ':', 1, -1 ) );
|
||||
return( QString::fromUtf8( mimeData->data( mimeType() ) ).section( ':', 1, -1 ) );
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include <QApplication>
|
||||
#include <QLayout>
|
||||
@@ -157,50 +158,75 @@ void TrackContainerView::removeTrackView( TrackView * _tv )
|
||||
|
||||
|
||||
|
||||
void TrackContainerView::moveTrackViewUp( TrackView * _tv )
|
||||
void TrackContainerView::moveTrackView( TrackView * trackView, int indexTo )
|
||||
{
|
||||
for( int i = 1; i < m_trackViews.size(); ++i )
|
||||
{
|
||||
TrackView * t = m_trackViews[i];
|
||||
if( t == _tv )
|
||||
{
|
||||
BBTrack::swapBBTracks( t->getTrack(),
|
||||
m_trackViews[i - 1]->getTrack() );
|
||||
m_scrollLayout->removeWidget( t );
|
||||
m_scrollLayout->insertWidget( i - 1, t );
|
||||
qSwap( m_tc->m_tracks[i-1], m_tc->m_tracks[i] );
|
||||
m_trackViews.swap( i - 1, i );
|
||||
realignTracks();
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Can't move out of bounds
|
||||
if ( indexTo >= m_trackViews.size() || indexTo < 0 ) { return; }
|
||||
|
||||
// Does not need to move to itself
|
||||
int indexFrom = m_trackViews.indexOf( trackView );
|
||||
if ( indexFrom == indexTo ) { return; }
|
||||
|
||||
BBTrack::swapBBTracks( trackView->getTrack(),
|
||||
m_trackViews[indexTo]->getTrack() );
|
||||
|
||||
m_scrollLayout->removeWidget( trackView );
|
||||
m_scrollLayout->insertWidget( indexTo, trackView );
|
||||
|
||||
Track * track = m_tc->m_tracks[indexFrom];
|
||||
|
||||
m_tc->m_tracks.remove( indexFrom );
|
||||
m_tc->m_tracks.insert( indexTo, track );
|
||||
m_trackViews.move( indexFrom, indexTo );
|
||||
|
||||
realignTracks();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void TrackContainerView::moveTrackViewDown( TrackView * _tv )
|
||||
void TrackContainerView::moveTrackViewUp( TrackView * trackView )
|
||||
{
|
||||
for( int i = 0; i < m_trackViews.size()-1; ++i )
|
||||
{
|
||||
TrackView * t = m_trackViews[i];
|
||||
if( t == _tv )
|
||||
{
|
||||
BBTrack::swapBBTracks( t->getTrack(),
|
||||
m_trackViews[i + 1]->getTrack() );
|
||||
m_scrollLayout->removeWidget( t );
|
||||
m_scrollLayout->insertWidget( i + 1, t );
|
||||
qSwap( m_tc->m_tracks[i], m_tc->m_tracks[i+1] );
|
||||
m_trackViews.swap( i, i + 1 );
|
||||
realignTracks();
|
||||
break;
|
||||
}
|
||||
}
|
||||
int index = m_trackViews.indexOf( trackView );
|
||||
|
||||
moveTrackView( trackView, index - 1 );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void TrackContainerView::moveTrackViewDown( TrackView * trackView )
|
||||
{
|
||||
int index = m_trackViews.indexOf( trackView );
|
||||
|
||||
moveTrackView( trackView, index + 1 );
|
||||
}
|
||||
|
||||
void TrackContainerView::scrollToTrackView( TrackView * _tv )
|
||||
{
|
||||
if (!m_trackViews.contains(_tv))
|
||||
{
|
||||
qWarning("TrackContainerView::scrollToTrackView: TrackView is not owned by this");
|
||||
}
|
||||
else
|
||||
{
|
||||
int currentScrollTop = m_scrollArea->verticalScrollBar()->value();
|
||||
int scrollAreaHeight = m_scrollArea->size().height();
|
||||
int trackViewTop = _tv->pos().y();
|
||||
int trackViewBottom = trackViewTop + _tv->size().height();
|
||||
|
||||
// displayed_location = widget_location - currentScrollTop
|
||||
// want to make sure that the widget top has displayed location > 0,
|
||||
// and widget bottom < scrollAreaHeight
|
||||
// trackViewTop - scrollY > 0 && trackViewBottom - scrollY < scrollAreaHeight
|
||||
// therefore scrollY < trackViewTop && scrollY > trackViewBottom - scrollAreaHeight
|
||||
int newScroll = std::max( trackViewBottom-scrollAreaHeight, std::min(currentScrollTop, trackViewTop) );
|
||||
m_scrollArea->verticalScrollBar()->setValue(newScroll);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void TrackContainerView::realignTracks()
|
||||
{
|
||||
@@ -220,11 +246,18 @@ void TrackContainerView::realignTracks()
|
||||
|
||||
|
||||
|
||||
void TrackContainerView::createTrackView( Track * _t )
|
||||
TrackView * TrackContainerView::createTrackView( Track * _t )
|
||||
{
|
||||
//m_tc->addJournalCheckPoint();
|
||||
|
||||
_t->createView( this );
|
||||
// Avoid duplicating track views
|
||||
for( trackViewList::iterator it = m_trackViews.begin();
|
||||
it != m_trackViews.end(); ++it )
|
||||
{
|
||||
if ( ( *it )->getTrack() == _t ) { return ( *it ); }
|
||||
}
|
||||
|
||||
return _t->createView( this );
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -624,11 +624,6 @@ void AutomationEditor::mouseMoveEvent(QMouseEvent * mouseEvent )
|
||||
float level = getLevel( mouseEvent->y() );
|
||||
int x = mouseEvent->x();
|
||||
|
||||
if( mouseEvent->x() <= VALUES_WIDTH )
|
||||
{
|
||||
update();
|
||||
return;
|
||||
}
|
||||
x -= VALUES_WIDTH;
|
||||
if( m_action == MOVE_VALUE )
|
||||
{
|
||||
@@ -699,12 +694,12 @@ void AutomationEditor::mouseMoveEvent(QMouseEvent * mouseEvent )
|
||||
{
|
||||
if( QApplication::overrideCursor() )
|
||||
{
|
||||
if( QApplication::overrideCursor()->shape() != Qt::SizeAllCursor )
|
||||
if( QApplication::overrideCursor()->shape() != Qt::SizeAllCursor )
|
||||
{
|
||||
while( QApplication::overrideCursor() != NULL )
|
||||
{
|
||||
QApplication::restoreOverrideCursor();
|
||||
}
|
||||
while( QApplication::overrideCursor() != NULL )
|
||||
{
|
||||
QApplication::restoreOverrideCursor();
|
||||
}
|
||||
|
||||
QCursor c( Qt::SizeAllCursor );
|
||||
QApplication::setOverrideCursor(
|
||||
@@ -2304,7 +2299,15 @@ void AutomationEditorWindow::dropEvent( QDropEvent *_de )
|
||||
journallingObject( val.toInt() ) );
|
||||
if( mod != NULL )
|
||||
{
|
||||
m_editor->m_pattern->addObject( mod );
|
||||
bool added = m_editor->m_pattern->addObject( mod );
|
||||
if ( !added )
|
||||
{
|
||||
TextFloat::displayMessage( mod->displayName(),
|
||||
tr( "Model is already connected "
|
||||
"to this pattern." ),
|
||||
embed::getIconPixmap( "automation" ),
|
||||
2000 );
|
||||
}
|
||||
setCurrentPattern( m_editor->m_pattern );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1081,7 +1081,16 @@ void PianoRoll::keyPressEvent(QKeyEvent* ke )
|
||||
if( ke->modifiers() & Qt::ControlModifier )
|
||||
{
|
||||
ke->accept();
|
||||
selectAll();
|
||||
if (ke->modifiers() & Qt::ShiftModifier)
|
||||
{
|
||||
// Ctrl + Shift + A = deselect all notes
|
||||
clearSelectedNotes();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Ctrl + A = select all notes
|
||||
selectAll();
|
||||
}
|
||||
update();
|
||||
}
|
||||
break;
|
||||
@@ -1848,54 +1857,50 @@ void PianoRoll::computeSelectedNotes(bool shift)
|
||||
|
||||
|
||||
|
||||
void PianoRoll::mouseReleaseEvent(QMouseEvent * me )
|
||||
void PianoRoll::mouseReleaseEvent( QMouseEvent * me )
|
||||
{
|
||||
s_textFloat->hide();
|
||||
bool mustRepaint = false;
|
||||
|
||||
s_textFloat->hide();
|
||||
|
||||
if( me->button() & Qt::LeftButton )
|
||||
{
|
||||
m_mouseDownLeft = false;
|
||||
mustRepaint = true;
|
||||
|
||||
if( m_action == ActionSelectNotes && m_editMode == ModeSelect )
|
||||
{
|
||||
// select the notes within the selection rectangle and
|
||||
// then destroy the selection rectangle
|
||||
computeSelectedNotes(
|
||||
me->modifiers() & Qt::ShiftModifier );
|
||||
}
|
||||
else if( m_action == ActionMoveNote )
|
||||
{
|
||||
// we moved one or more notes so they have to be
|
||||
// moved properly according to new starting-
|
||||
// time in the note-array of pattern
|
||||
m_pattern->rearrangeAllNotes();
|
||||
|
||||
}
|
||||
|
||||
if( m_action == ActionMoveNote || m_action == ActionResizeNote )
|
||||
{
|
||||
// if we only moved one note, deselect it so we can
|
||||
// edit the notes in the note edit area
|
||||
if( selectionCount() == 1 )
|
||||
{
|
||||
clearSelectedNotes();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( me->button() & Qt::RightButton )
|
||||
{
|
||||
m_mouseDownRight = false;
|
||||
mustRepaint = true;
|
||||
}
|
||||
|
||||
if( me->button() & Qt::LeftButton &&
|
||||
m_editMode == ModeSelect &&
|
||||
m_action == ActionSelectNotes )
|
||||
{
|
||||
// select the notes within the selection rectangle and
|
||||
// then destroy the selection rectangle
|
||||
|
||||
computeSelectedNotes( me->modifiers() & Qt::ShiftModifier );
|
||||
|
||||
}
|
||||
else if( me->button() & Qt::LeftButton &&
|
||||
m_action == ActionMoveNote )
|
||||
{
|
||||
// we moved one or more notes so they have to be
|
||||
// moved properly according to new starting-
|
||||
// time in the note-array of pattern
|
||||
|
||||
m_pattern->rearrangeAllNotes();
|
||||
|
||||
}
|
||||
if( me->button() & Qt::LeftButton &&
|
||||
( m_action == ActionMoveNote || m_action == ActionResizeNote ) )
|
||||
{
|
||||
// if we only moved one note, deselect it so we can
|
||||
// edit the notes in the note edit area
|
||||
if( selectionCount() == 1 )
|
||||
{
|
||||
clearSelectedNotes();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if( hasValidPattern() )
|
||||
{
|
||||
// turn off all notes that are playing
|
||||
@@ -1907,7 +1912,8 @@ void PianoRoll::mouseReleaseEvent(QMouseEvent * me )
|
||||
Note *note = *it;
|
||||
if( note->isPlaying() )
|
||||
{
|
||||
m_pattern->instrumentTrack()->pianoModel()->handleKeyRelease( note->key() );
|
||||
m_pattern->instrumentTrack()->pianoModel()->
|
||||
handleKeyRelease( note->key() );
|
||||
note->setIsPlaying( false );
|
||||
}
|
||||
|
||||
@@ -1915,11 +1921,11 @@ void PianoRoll::mouseReleaseEvent(QMouseEvent * me )
|
||||
}
|
||||
|
||||
// stop playing keys that we let go of
|
||||
m_pattern->instrumentTrack()->pianoModel()->handleKeyRelease( m_lastKey );
|
||||
m_pattern->instrumentTrack()->pianoModel()->
|
||||
handleKeyRelease( m_lastKey );
|
||||
}
|
||||
|
||||
m_currentNote = NULL;
|
||||
|
||||
m_action = ActionNone;
|
||||
|
||||
if( m_editMode == ModeDraw )
|
||||
@@ -2092,7 +2098,7 @@ void PianoRoll::mouseMoveEvent( QMouseEvent * me )
|
||||
if ( isUnderPosition ) { testPlayNote( n ); }
|
||||
// If note is the one under the cursor or is selected when alt is
|
||||
// not pressed
|
||||
if ( isUnderPosition || ( n->selected() && !altPressed ) )
|
||||
if ( ( isUnderPosition && !isSelection() ) || ( n->selected() && !altPressed ) )
|
||||
{
|
||||
if( m_noteEditMode == NoteEditVolume )
|
||||
{
|
||||
@@ -2428,7 +2434,7 @@ void PianoRoll::dragNotes( int x, int y, bool alt, bool shift, bool ctrl )
|
||||
{
|
||||
if( m_moveBoundaryLeft + off_ticks < 0 )
|
||||
{
|
||||
off_ticks += 0 - (off_ticks + m_moveBoundaryLeft);
|
||||
off_ticks -= (off_ticks + m_moveBoundaryLeft);
|
||||
}
|
||||
if( m_moveBoundaryTop + off_key > NumKeys )
|
||||
{
|
||||
@@ -2436,92 +2442,161 @@ void PianoRoll::dragNotes( int x, int y, bool alt, bool shift, bool ctrl )
|
||||
}
|
||||
if( m_moveBoundaryBottom + off_key < 0 )
|
||||
{
|
||||
off_key += 0 - (m_moveBoundaryBottom + off_key);
|
||||
off_key -= (m_moveBoundaryBottom + off_key);
|
||||
}
|
||||
}
|
||||
|
||||
int shift_offset = 0;
|
||||
int shift_ref_pos = -1;
|
||||
|
||||
// get note-vector of current pattern
|
||||
const NoteVector & notes = m_pattern->notes();
|
||||
|
||||
// will be our iterator in the following loop
|
||||
NoteVector::ConstIterator it = notes.begin();
|
||||
|
||||
int sNotes = selectionCount();
|
||||
while( it != notes.end() )
|
||||
if (m_action == ActionMoveNote)
|
||||
{
|
||||
Note *note = *it;
|
||||
const int pos = note->pos().getTicks();
|
||||
for (NoteVector::ConstIterator it = notes.begin(); it != notes.end(); ++it )
|
||||
{
|
||||
Note *note = *it;
|
||||
if( note->selected() )
|
||||
{
|
||||
if( ! ( shift && ! m_startedWithShift ) )
|
||||
{
|
||||
// moving note
|
||||
int pos_ticks = note->oldPos().getTicks() + off_ticks;
|
||||
int key_num = note->oldKey() + off_key;
|
||||
|
||||
// ticks can't be negative
|
||||
pos_ticks = qMax(0, pos_ticks);
|
||||
// upper/lower bound checks on key_num
|
||||
key_num = qMax(0, key_num);
|
||||
key_num = qMin(key_num, NumKeys);
|
||||
|
||||
note->setPos( MidiTime( pos_ticks ) );
|
||||
note->setKey( key_num );
|
||||
}
|
||||
else if( shift && ! m_startedWithShift )
|
||||
{
|
||||
// quick resize, toggled by holding shift after starting a note move, but not before
|
||||
int ticks_new = note->oldLength().getTicks() + off_ticks;
|
||||
if( ticks_new <= 0 )
|
||||
{
|
||||
ticks_new = 1;
|
||||
}
|
||||
note->setLength( MidiTime( ticks_new ) );
|
||||
m_lenOfNewNotes = note->length();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (m_action == ActionResizeNote)
|
||||
{
|
||||
// When resizing notes:
|
||||
// If shift is not pressed, resize the selected notes but do not rearrange them
|
||||
// If shift is pressed we resize and rearrange only the selected notes
|
||||
// If shift + ctrl then we also rearrange all posterior notes (sticky)
|
||||
// If shift is pressed but only one note is selected, apply sticky
|
||||
if( m_action == ActionResizeNote && shift &&
|
||||
( note->selected() || ctrl || sNotes == 1 ) )
|
||||
|
||||
if (shift)
|
||||
{
|
||||
int shifted_pos = note->oldPos().getTicks() + shift_offset;
|
||||
if( shifted_pos && pos == shift_ref_pos )
|
||||
// Algorithm:
|
||||
// Relative to the starting point of the left-most selected note,
|
||||
// all selected note start-points and *endpoints* (not length) should be scaled by a calculated factor.
|
||||
// This factor is such that the endpoint of the note whose handle is being dragged should lie under the cursor.
|
||||
// first, determine the start-point of the left-most selected note:
|
||||
int stretchStartTick = -1;
|
||||
for (NoteVector::ConstIterator it = notes.begin(); it != notes.end(); ++it )
|
||||
{
|
||||
shifted_pos -= off_ticks;
|
||||
}
|
||||
note->setPos( MidiTime( shifted_pos ) );
|
||||
}
|
||||
|
||||
if( note->selected() )
|
||||
{
|
||||
if( m_action == ActionMoveNote && ! ( shift && ! m_startedWithShift ) )
|
||||
{
|
||||
// moving note
|
||||
int pos_ticks = note->oldPos().getTicks() + off_ticks;
|
||||
int key_num = note->oldKey() + off_key;
|
||||
|
||||
// ticks can't be negative
|
||||
pos_ticks = qMax(0, pos_ticks);
|
||||
// upper/lower bound checks on key_num
|
||||
key_num = qMax(0, key_num);
|
||||
key_num = qMin(key_num, NumKeys);
|
||||
|
||||
note->setPos( MidiTime( pos_ticks ) );
|
||||
note->setKey( key_num );
|
||||
}
|
||||
else if( m_action == ActionResizeNote )
|
||||
{
|
||||
// resizing note
|
||||
int ticks_new = note->oldLength().getTicks() + off_ticks;
|
||||
if( ticks_new <= 0 )
|
||||
Note *note = *it;
|
||||
if (note->selected() && (stretchStartTick < 0 || note->oldPos().getTicks() < stretchStartTick))
|
||||
{
|
||||
ticks_new = 1;
|
||||
stretchStartTick = note->oldPos().getTicks();
|
||||
}
|
||||
else if( shift )
|
||||
}
|
||||
// determine the ending tick of the right-most selected note
|
||||
Note *posteriorNote = nullptr;
|
||||
for (NoteVector::ConstIterator it = notes.begin(); it != notes.end(); ++it )
|
||||
{
|
||||
Note *note = *it;
|
||||
if (note->selected() && (posteriorNote == nullptr ||
|
||||
note->oldPos().getTicks() + note->oldLength().getTicks() >
|
||||
posteriorNote->oldPos().getTicks() + posteriorNote->oldLength().getTicks()))
|
||||
{
|
||||
// when holding shift: update the offset used to shift
|
||||
// the following notes
|
||||
if( pos > shift_ref_pos )
|
||||
posteriorNote = note;
|
||||
}
|
||||
}
|
||||
int posteriorEndTick = posteriorNote->pos().getTicks() + posteriorNote->length().getTicks();
|
||||
// end-point of the note whose handle is being dragged:
|
||||
int stretchEndTick = m_currentNote->oldPos().getTicks() + m_currentNote->oldLength().getTicks();
|
||||
// Calculate factor by which to scale the start-point and end-point of all selected notes
|
||||
float scaleFactor = (float)(stretchEndTick - stretchStartTick + off_ticks) / qMax(1, stretchEndTick - stretchStartTick);
|
||||
scaleFactor = qMax(0.0f, scaleFactor);
|
||||
|
||||
// process all selected notes & determine how much the endpoint of the right-most note was shifted
|
||||
int posteriorDeltaThisFrame = 0;
|
||||
for (NoteVector::ConstIterator it = notes.begin(); it != notes.end(); ++it )
|
||||
{
|
||||
Note *note = *it;
|
||||
if(note->selected())
|
||||
{
|
||||
// scale relative start and end positions by scaleFactor
|
||||
int newStart = stretchStartTick + scaleFactor *
|
||||
(note->oldPos().getTicks() - stretchStartTick);
|
||||
int newEnd = stretchStartTick + scaleFactor *
|
||||
(note->oldPos().getTicks()+note->oldLength().getTicks() - stretchStartTick);
|
||||
// if not holding alt, quantize the offsets
|
||||
if(!alt)
|
||||
{
|
||||
shift_offset += off_ticks;
|
||||
shift_ref_pos = pos;
|
||||
// quantize start time
|
||||
int oldStart = note->oldPos().getTicks();
|
||||
int startDiff = newStart - oldStart;
|
||||
startDiff = floor(startDiff / quantization()) * quantization();
|
||||
newStart = oldStart + startDiff;
|
||||
// quantize end time
|
||||
int oldEnd = oldStart + note->oldLength().getTicks();
|
||||
int endDiff = newEnd - oldEnd;
|
||||
endDiff = floor(endDiff / quantization()) * quantization();
|
||||
newEnd = oldEnd + endDiff;
|
||||
}
|
||||
int newLength = qMax(1, newEnd-newStart);
|
||||
if (note == posteriorNote)
|
||||
{
|
||||
posteriorDeltaThisFrame = (newStart+newLength) -
|
||||
(note->pos().getTicks() + note->length().getTicks());
|
||||
}
|
||||
note->setLength( MidiTime(newLength) );
|
||||
note->setPos( MidiTime(newStart) );
|
||||
|
||||
m_lenOfNewNotes = note->length();
|
||||
}
|
||||
}
|
||||
if (ctrl || selectionCount() == 1)
|
||||
{
|
||||
// if holding ctrl or only one note is selected, reposition posterior notes
|
||||
for (NoteVector::ConstIterator it = notes.begin(); it != notes.end(); ++it )
|
||||
{
|
||||
Note *note = *it;
|
||||
if (!note->selected() && note->pos().getTicks() >= posteriorEndTick)
|
||||
{
|
||||
int newStart = note->pos().getTicks() + posteriorDeltaThisFrame;
|
||||
note->setPos( MidiTime(newStart) );
|
||||
}
|
||||
}
|
||||
note->setLength( MidiTime( ticks_new ) );
|
||||
|
||||
m_lenOfNewNotes = note->length();
|
||||
}
|
||||
else if( m_action == ActionMoveNote && ( shift && ! m_startedWithShift ) )
|
||||
{
|
||||
// quick resize, toggled by holding shift after starting a note move, but not before
|
||||
int ticks_new = note->oldLength().getTicks() + off_ticks;
|
||||
if( ticks_new <= 0 )
|
||||
{
|
||||
ticks_new = 1;
|
||||
}
|
||||
note->setLength( MidiTime( ticks_new ) );
|
||||
m_lenOfNewNotes = note->length();
|
||||
}
|
||||
}
|
||||
++it;
|
||||
else
|
||||
{
|
||||
// shift is not pressed; stretch length of selected notes but not their position
|
||||
for (NoteVector::ConstIterator it = notes.begin(); it != notes.end(); ++it )
|
||||
{
|
||||
Note *note = *it;
|
||||
if (note->selected())
|
||||
{
|
||||
int newLength = note->oldLength() + off_ticks;
|
||||
newLength = qMax(1, newLength);
|
||||
note->setLength( MidiTime(newLength) );
|
||||
|
||||
m_lenOfNewNotes = note->length();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_pattern->dataChanged();
|
||||
@@ -4230,3 +4305,9 @@ QSize PianoRollWindow::sizeHint() const
|
||||
{
|
||||
return {m_toolBar->sizeHint().width() + 10, INITIAL_PIANOROLL_HEIGHT};
|
||||
}
|
||||
|
||||
void PianoRollWindow::focusInEvent(QFocusEvent * event)
|
||||
{
|
||||
// when the window is given focus, also give focus to the actual piano roll
|
||||
m_editor->setFocus(event->reason());
|
||||
}
|
||||
|
||||
@@ -67,7 +67,6 @@ QPixmap * Fader::s_knob = NULL;
|
||||
Fader::Fader( FloatModel * _model, const QString & _name, QWidget * _parent ) :
|
||||
QWidget( _parent ),
|
||||
FloatModelView( _model, this ),
|
||||
m_model( _model ),
|
||||
m_fPeakValue_L( 0.0 ),
|
||||
m_fPeakValue_R( 0.0 ),
|
||||
m_persistentPeak_L( 0.0 ),
|
||||
@@ -114,7 +113,6 @@ Fader::Fader( FloatModel * _model, const QString & _name, QWidget * _parent ) :
|
||||
Fader::Fader( FloatModel * model, const QString & name, QWidget * parent, QPixmap * back, QPixmap * leds, QPixmap * knob ) :
|
||||
QWidget( parent ),
|
||||
FloatModelView( model, this ),
|
||||
m_model( model ),
|
||||
m_fPeakValue_L( 0.0 ),
|
||||
m_fPeakValue_R( 0.0 ),
|
||||
m_persistentPeak_L( 0.0 ),
|
||||
@@ -170,7 +168,7 @@ void Fader::mouseMoveEvent( QMouseEvent *mouseEvent )
|
||||
{
|
||||
int dy = m_moveStartPoint - mouseEvent->globalY();
|
||||
|
||||
float delta = dy * ( m_model->maxValue() - m_model->minValue() ) / (float) ( height() - ( *m_knob ).height() );
|
||||
float delta = dy * ( model()->maxValue() - model()->minValue() ) / (float) ( height() - ( *m_knob ).height() );
|
||||
|
||||
model()->setValue( m_startValue + delta );
|
||||
|
||||
@@ -256,11 +254,11 @@ void Fader::wheelEvent ( QWheelEvent *ev )
|
||||
|
||||
if ( ev->delta() > 0 )
|
||||
{
|
||||
m_model->incValue( 1 );
|
||||
model()->incValue( 1 );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_model->incValue( -1 );
|
||||
model()->incValue( -1 );
|
||||
}
|
||||
updateTextFloat();
|
||||
s_textFloat->setVisibilityTimeOut( 1000 );
|
||||
@@ -326,7 +324,7 @@ void Fader::updateTextFloat()
|
||||
}
|
||||
else
|
||||
{
|
||||
s_textFloat->setText( m_description + " " + QString("%1 ").arg( m_displayConversion ? m_model->value() * 100 : m_model->value() ) + " " + m_unit );
|
||||
s_textFloat->setText( m_description + " " + QString("%1 ").arg( m_displayConversion ? model()->value() * 100 : model()->value() ) + " " + m_unit );
|
||||
}
|
||||
s_textFloat->moveGlobal( this, QPoint( width() - ( *m_knob ).width() - 5, knobPosY() - 46 ) );
|
||||
}
|
||||
|
||||
@@ -65,7 +65,8 @@ TextFloat * Knob::s_textFloat = NULL;
|
||||
m_volumeKnob( false ), \
|
||||
m_volumeRatio( 100.0, 0.0, 1000000.0 ), \
|
||||
m_buttonPressed( false ), \
|
||||
m_angle( -10 )
|
||||
m_angle( -10 ), \
|
||||
m_lineWidth(0)
|
||||
|
||||
Knob::Knob( knobTypes _knob_num, QWidget * _parent, const QString & _name ) :
|
||||
DEFAULT_KNOB_INITIALIZER_LIST,
|
||||
|
||||
91
src/gui/widgets/LeftRightNav.cpp
Normal file
91
src/gui/widgets/LeftRightNav.cpp
Normal file
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* LeftRightNav.cpp - side-by-side left-facing and right-facing arrows for navigation (looks like < > )
|
||||
*
|
||||
* Copyright (c) 2015 Colin Wallace <wallacoloo/at/gmail.com>
|
||||
*
|
||||
* This file is part of LMMS - http://lmms.io
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public
|
||||
* License along with this program (see COPYING); if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
* Boston, MA 02110-1301 USA.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include "LeftRightNav.h"
|
||||
#include "ToolTip.h"
|
||||
#include "embed.h"
|
||||
|
||||
|
||||
LeftRightNav::LeftRightNav(QWidget *parent)
|
||||
: QWidget(parent),
|
||||
m_layout(this),
|
||||
m_leftBtn(this, tr("Previous")),
|
||||
m_rightBtn(this, tr("Next"))
|
||||
{
|
||||
m_layout.setContentsMargins(0, 0, 0, 0);
|
||||
m_layout.setSpacing(2);
|
||||
|
||||
m_leftBtn.setCheckable(false);
|
||||
m_rightBtn.setCheckable(false);
|
||||
|
||||
m_leftBtn.setCursor(Qt::PointingHandCursor);
|
||||
m_rightBtn.setCursor(Qt::PointingHandCursor);
|
||||
|
||||
m_leftBtn.setActiveGraphic(embed::getIconPixmap(
|
||||
"stepper-left-press"));
|
||||
m_rightBtn.setActiveGraphic(embed::getIconPixmap(
|
||||
"stepper-right-press" ));
|
||||
|
||||
m_leftBtn.setInactiveGraphic(embed::getIconPixmap(
|
||||
"stepper-left" ));
|
||||
m_rightBtn.setInactiveGraphic(embed::getIconPixmap(
|
||||
"stepper-right"));
|
||||
|
||||
connect(&m_leftBtn, SIGNAL(clicked()), this,
|
||||
SIGNAL(onNavLeft()));
|
||||
connect(&m_rightBtn, SIGNAL(clicked()), this,
|
||||
SIGNAL(onNavRight()));
|
||||
|
||||
ToolTip::add(&m_leftBtn, tr("Previous"));
|
||||
ToolTip::add(&m_rightBtn, tr("Next"));
|
||||
|
||||
m_leftBtn.setWindowTitle(tr("Previous"));
|
||||
m_rightBtn.setWindowTitle(tr("Next"));
|
||||
|
||||
// AutomatableButton's right click menu (contains irrelevant options like copying and pasting values)
|
||||
m_leftBtn.setContextMenuPolicy(Qt::NoContextMenu);
|
||||
m_rightBtn.setContextMenuPolicy(Qt::NoContextMenu);
|
||||
|
||||
m_layout.addWidget(&m_leftBtn);
|
||||
m_layout.addWidget(&m_rightBtn);
|
||||
}
|
||||
|
||||
PixmapButton* LeftRightNav::getLeftBtn()
|
||||
{
|
||||
return &m_leftBtn;
|
||||
}
|
||||
PixmapButton* LeftRightNav::getRightBtn()
|
||||
{
|
||||
return &m_rightBtn;
|
||||
}
|
||||
|
||||
void LeftRightNav::setShortcuts(const QKeySequence &leftShortcut, const QKeySequence &rightShortcut)
|
||||
{
|
||||
m_leftBtn.setShortcut(leftShortcut);
|
||||
m_rightBtn.setShortcut(rightShortcut);
|
||||
|
||||
ToolTip::add(&m_leftBtn, tr("Previous (%1)").arg(leftShortcut.toString()));
|
||||
ToolTip::add(&m_rightBtn, tr("Next (%1)").arg(rightShortcut.toString()));
|
||||
}
|
||||
@@ -130,7 +130,17 @@ void PixmapButton::setInactiveGraphic( const QPixmap & _pm, bool _update )
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
QSize PixmapButton::sizeHint() const
|
||||
{
|
||||
if( ( model() != NULL && model()->value() ) || m_pressed )
|
||||
{
|
||||
return m_activePixmap.size();
|
||||
}
|
||||
else
|
||||
{
|
||||
return m_inactivePixmap.size();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -66,6 +66,7 @@
|
||||
#include "Knob.h"
|
||||
#include "LcdSpinBox.h"
|
||||
#include "LedCheckbox.h"
|
||||
#include "LeftRightNav.h"
|
||||
#include "MainWindow.h"
|
||||
#include "MidiClient.h"
|
||||
#include "MidiPortMenu.h"
|
||||
@@ -80,6 +81,7 @@
|
||||
#include "StringPairDrag.h"
|
||||
#include "TabWidget.h"
|
||||
#include "ToolTip.h"
|
||||
#include "TrackContainerView.h"
|
||||
#include "TrackLabelButton.h"
|
||||
#include "ValueBuffer.h"
|
||||
#include "volume.h"
|
||||
@@ -1280,13 +1282,36 @@ InstrumentTrackWindow::InstrumentTrackWindow( InstrumentTrackView * _itv ) :
|
||||
generalSettingsLayout->setContentsMargins( 8, 18, 8, 8 );
|
||||
generalSettingsLayout->setSpacing( 6 );
|
||||
|
||||
QWidget* nameAndChangeTrackWidget = new QWidget( generalSettingsWidget );
|
||||
QHBoxLayout* nameAndChangeTrackLayout = new QHBoxLayout( nameAndChangeTrackWidget );
|
||||
nameAndChangeTrackLayout->setContentsMargins( 0, 0, 0, 0 );
|
||||
nameAndChangeTrackLayout->setSpacing( 2 );
|
||||
|
||||
// setup line edit for changing instrument track name
|
||||
m_nameLineEdit = new QLineEdit;
|
||||
m_nameLineEdit->setFont( pointSize<9>( m_nameLineEdit->font() ) );
|
||||
connect( m_nameLineEdit, SIGNAL( textChanged( const QString & ) ),
|
||||
this, SLOT( textChanged( const QString & ) ) );
|
||||
|
||||
generalSettingsLayout->addWidget( m_nameLineEdit );
|
||||
m_nameLineEdit->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred));
|
||||
nameAndChangeTrackLayout->addWidget(m_nameLineEdit);
|
||||
|
||||
|
||||
// set up left/right arrows for changing instrument
|
||||
m_leftRightNav = new LeftRightNav(this);
|
||||
connect( m_leftRightNav, SIGNAL( onNavLeft() ), this,
|
||||
SLOT( viewPrevInstrument() ) );
|
||||
connect( m_leftRightNav, SIGNAL( onNavRight() ), this,
|
||||
SLOT( viewNextInstrument() ) );
|
||||
m_leftRightNav->setWhatsThis(
|
||||
tr( "Use these controls to view and edit the next/previous track in the song editor." ) );
|
||||
// m_leftRightNav->setShortcuts();
|
||||
nameAndChangeTrackLayout->addWidget(m_leftRightNav);
|
||||
|
||||
|
||||
generalSettingsLayout->addWidget( nameAndChangeTrackWidget );
|
||||
|
||||
|
||||
|
||||
QHBoxLayout* basicControlsLayout = new QHBoxLayout;
|
||||
basicControlsLayout->setSpacing( 3 );
|
||||
@@ -1693,3 +1718,61 @@ void InstrumentTrackWindow::loadSettings( const QDomElement& thisElement )
|
||||
m_itv->m_tlb->setChecked( true );
|
||||
}
|
||||
}
|
||||
|
||||
void InstrumentTrackWindow::viewInstrumentInDirection(int d)
|
||||
{
|
||||
// helper routine for viewNextInstrument, viewPrevInstrument
|
||||
// d=-1 to view the previous instrument,
|
||||
// d=+1 to view the next instrument
|
||||
|
||||
const QList<TrackView *> &trackViews = m_itv->trackContainerView()->trackViews();
|
||||
int idxOfMe = trackViews.indexOf(m_itv);
|
||||
|
||||
// search for the next InstrumentTrackView (i.e. skip AutomationViews, etc)
|
||||
// sometimes, the next InstrumentTrackView may already be open, in which case
|
||||
// replace our window contents with the *next* closed Instrument Track and
|
||||
// give focus to the InstrumentTrackView we skipped.
|
||||
int idxOfNext = idxOfMe;
|
||||
InstrumentTrackView *newView = nullptr;
|
||||
InstrumentTrackView *bringToFront = nullptr;
|
||||
do
|
||||
{
|
||||
idxOfNext = (idxOfNext + d + trackViews.size()) % trackViews.size();
|
||||
newView = dynamic_cast<InstrumentTrackView*>(trackViews[idxOfNext]);
|
||||
// the window that should be brought to focus is the FIRST InstrumentTrackView that comes after us
|
||||
if (bringToFront == nullptr && newView != nullptr)
|
||||
{
|
||||
bringToFront = newView;
|
||||
}
|
||||
// if the next instrument doesn't have an active window, then exit loop & load that one into our window.
|
||||
if (newView != nullptr && !newView->m_tlb->isChecked())
|
||||
{
|
||||
break;
|
||||
}
|
||||
} while (idxOfNext != idxOfMe);
|
||||
|
||||
// avoid reloading the window if there is only one instrument, as that will just change the active tab
|
||||
if (idxOfNext != idxOfMe)
|
||||
{
|
||||
// save current window pos and then hide the window by unchecking its button in the track list
|
||||
QPoint curPos = parentWidget()->pos();
|
||||
m_itv->m_tlb->setChecked(false);
|
||||
|
||||
// enable the new window by checking its track list button & moving it to where our window just was
|
||||
newView->m_tlb->setChecked(true);
|
||||
newView->getInstrumentTrackWindow()->parentWidget()->move(curPos);
|
||||
|
||||
// scroll the SongEditor/BB-editor to make sure the new trackview label is visible
|
||||
bringToFront->trackContainerView()->scrollToTrackView(bringToFront);
|
||||
}
|
||||
bringToFront->getInstrumentTrackWindow()->setFocus();
|
||||
}
|
||||
|
||||
void InstrumentTrackWindow::viewNextInstrument()
|
||||
{
|
||||
viewInstrumentInDirection(+1);
|
||||
}
|
||||
void InstrumentTrackWindow::viewPrevInstrument()
|
||||
{
|
||||
viewInstrumentInDirection(-1);
|
||||
}
|
||||
Reference in New Issue
Block a user