() )
- {
- 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 = "" + tr("Name") + ": " + QString::fromUtf8(descriptor.displayName) + "
";
+ labelText += "" + tr("Description") + ": " + QString::fromUtf8(descriptor.description) + "
";
+ labelText += "" + tr("Author") + ": " + QString::fromUtf8(descriptor.author) + "
";
+
+ 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() )
+ {
+ if( w->parent() == subWidget )
+ {
+ subLayout->addWidget( w );
+ }
+ }
+
+ textWidgetLayout->addWidget(subWidget);
+ }
+
+ ui->scrollArea->setWidget( m_descriptionWidget );
m_descriptionWidget->show();
}
}
diff --git a/src/gui/FileBrowser.cpp b/src/gui/FileBrowser.cpp
index e7d946acc..cd95e5a7d 100644
--- a/src/gui/FileBrowser.cpp
+++ b/src/gui/FileBrowser.cpp
@@ -32,6 +32,7 @@
#include
#include
#include
+#include
#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;
diff --git a/src/gui/Forms/EffectSelectDialog.ui b/src/gui/Forms/EffectSelectDialog.ui
index a58cd6c8c..a19233ac8 100644
--- a/src/gui/Forms/EffectSelectDialog.ui
+++ b/src/gui/Forms/EffectSelectDialog.ui
@@ -7,7 +7,7 @@
0
0
585
- 547
+ 550
@@ -40,41 +40,20 @@
-
-
-
-
- 0
- 200
-
+
+
+ QFrame::NoFrame
-
-
- 16777215
- 210
-
-
-
- Plugin description
-
-
-
-
-
-
- QFrame::NoFrame
-
-
-
-
- 0
- 0
- 497
- 109
-
-
-
-
-
-
+
+
+
+ 0
+ 0
+ 497
+ 109
+
+
+
-
diff --git a/src/gui/FxMixerView.cpp b/src/gui/FxMixerView.cpp
index 141a37619..2a8271048 100644
--- a/src/gui/FxMixerView.cpp
+++ b/src/gui/FxMixerView.cpp
@@ -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;
}
}
diff --git a/src/gui/GuiApplication.cpp b/src/gui/GuiApplication.cpp
index 78cf609ef..4a9b35f73 100644
--- a/src/gui/GuiApplication.cpp
+++ b/src/gui/GuiApplication.cpp
@@ -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();
+}
diff --git a/src/gui/LfoControllerDialog.cpp b/src/gui/LfoControllerDialog.cpp
index b7c3eced7..f13928969 100644
--- a/src/gui/LfoControllerDialog.cpp
+++ b/src/gui/LfoControllerDialog.cpp
@@ -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()
{
diff --git a/src/gui/MainWindow.cpp b/src/gui/MainWindow.cpp
index 154133882..80406ec7c 100644
--- a/src/gui/MainWindow.cpp
+++ b/src/gui/MainWindow.cpp
@@ -33,6 +33,7 @@
#include
#include
#include
+#include
#include
#include
@@ -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()
diff --git a/src/gui/SetupDialog.cpp b/src/gui/SetupDialog.cpp
index 91984f696..7ca9911ce 100644
--- a/src/gui/SetupDialog.cpp
+++ b/src/gui/SetupDialog.cpp
@@ -30,6 +30,7 @@
#include
#include
#include
+#include
#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
diff --git a/src/gui/StringPairDrag.cpp b/src/gui/StringPairDrag.cpp
index 244362a70..d9e01d065 100644
--- a/src/gui/StringPairDrag.cpp
+++ b/src/gui/StringPairDrag.cpp
@@ -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 ) );
}
diff --git a/src/gui/TrackContainerView.cpp b/src/gui/TrackContainerView.cpp
index e3471c444..94f6e0de7 100644
--- a/src/gui/TrackContainerView.cpp
+++ b/src/gui/TrackContainerView.cpp
@@ -22,6 +22,7 @@
*
*/
+#include
#include
#include
@@ -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 );
}
diff --git a/src/gui/editors/AutomationEditor.cpp b/src/gui/editors/AutomationEditor.cpp
index 3146d49b1..f51e7bce9 100644
--- a/src/gui/editors/AutomationEditor.cpp
+++ b/src/gui/editors/AutomationEditor.cpp
@@ -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 );
}
}
diff --git a/src/gui/editors/PianoRoll.cpp b/src/gui/editors/PianoRoll.cpp
index 5a6805657..1ca1a51ca 100644
--- a/src/gui/editors/PianoRoll.cpp
+++ b/src/gui/editors/PianoRoll.cpp
@@ -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());
+}
diff --git a/src/gui/widgets/Fader.cpp b/src/gui/widgets/Fader.cpp
index 0f0bef69d..d8055f5ac 100644
--- a/src/gui/widgets/Fader.cpp
+++ b/src/gui/widgets/Fader.cpp
@@ -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 ) );
}
diff --git a/src/gui/widgets/Knob.cpp b/src/gui/widgets/Knob.cpp
index 75732679d..7c6b26c36 100644
--- a/src/gui/widgets/Knob.cpp
+++ b/src/gui/widgets/Knob.cpp
@@ -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,
diff --git a/src/gui/widgets/LeftRightNav.cpp b/src/gui/widgets/LeftRightNav.cpp
new file mode 100644
index 000000000..530d128d7
--- /dev/null
+++ b/src/gui/widgets/LeftRightNav.cpp
@@ -0,0 +1,91 @@
+/*
+ * LeftRightNav.cpp - side-by-side left-facing and right-facing arrows for navigation (looks like < > )
+ *
+ * Copyright (c) 2015 Colin Wallace
+ *
+ * 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()));
+}
\ No newline at end of file
diff --git a/src/gui/widgets/PixmapButton.cpp b/src/gui/widgets/PixmapButton.cpp
index e647c5e23..44e957eef 100644
--- a/src/gui/widgets/PixmapButton.cpp
+++ b/src/gui/widgets/PixmapButton.cpp
@@ -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();
+ }
+}
diff --git a/src/tracks/InstrumentTrack.cpp b/src/tracks/InstrumentTrack.cpp
index d7e53d137..eb6a4a2b7 100644
--- a/src/tracks/InstrumentTrack.cpp
+++ b/src/tracks/InstrumentTrack.cpp
@@ -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 &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(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);
+}
\ No newline at end of file