Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

generating unique names for new tracks #7557

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions include/Track.h
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,8 @@ class LMMS_EXPORT Track : public Model, public JournallingObject

BoolModel* getMutedModel();

//! returns a name that isn't used by any track and conatins `sourceName`
QString findUniqueName(const QString& sourceName) const;
public slots:
virtual void setName(const QString& newName);

Expand All @@ -211,6 +213,9 @@ public slots:
void saveTrack(QDomDocument& doc, QDomElement& element, bool presetMode);
void loadTrack(const QDomElement& element, bool presetMode);

//! returns the number characters at the end of a string
static QString getNameNumberEnding(const QString& name, bool* isSeparatedWithWhiteSpace = nullptr);

private:
TrackContainer* m_trackContainer;
Type m_type;
Expand Down
71 changes: 71 additions & 0 deletions src/core/Track.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,8 @@ Track* Track::clone()
QDomElement parent = doc.createElement("clonedtrack");
saveState(doc, parent);
Track* t = create(parent.firstChild().toElement(), m_trackContainer);
// giving different name to cloned track
t->setName(findUniqueName(name()));

AutomationClip::resolveAllIDs();
return t;
Expand Down Expand Up @@ -652,6 +654,75 @@ BoolModel *Track::getMutedModel()
return &m_mutedModel;
}

QString Track::findUniqueName(const QString& sourceName) const
{
QString output = sourceName;
// removing number from `sourceName`
bool isSeparatedWithWhiteSpace = false;
size_t sourceNumberLength = Track::getNameNumberEnding(sourceName, &isSeparatedWithWhiteSpace).size();
if (sourceNumberLength > 0)
{
// whitespace needs to be removed so we add + 1 to `sourceNumberLength`
sourceNumberLength = isSeparatedWithWhiteSpace ? sourceNumberLength + 1 : sourceNumberLength;
output.remove(output.size() - sourceNumberLength, sourceNumberLength);
}

const TrackContainer::TrackList& trackList = m_trackContainer->tracks();

size_t maxNameCounter = 0;
bool found = false;

for (const Track* it : trackList)
{
if (it->name().startsWith(output))
{
size_t nameCount = Track::getNameNumberEnding(it->name()).toInt();
maxNameCounter = maxNameCounter < nameCount ? nameCount : maxNameCounter;
found = true;
}
}

if (found)
{
output = output + " " + QString::number(maxNameCounter + 1);
}

return output;
}

QString Track::getNameNumberEnding(const QString& name, bool* isSeparatedWithWhiteSpace)
{
QString numberString = "";

//! `it` will point to where the numbers start in `name`
auto it = name.end();
size_t digitCount = 0;
while (it != name.begin())
{
it--;
if (it->isDigit() == false)
{
if (isSeparatedWithWhiteSpace != nullptr)
{
*isSeparatedWithWhiteSpace = *it == ' ';
}
// the last character was not a number
// increase `it` to account for this (and make it point to a digit)
it++;
break;
}
digitCount++;
}

if (digitCount > 0)
{
numberString.resize(digitCount);
std::copy(it, name.end(), numberString.begin());
}

return numberString;
}

void Track::setName(const QString& newName)
{
if (m_name != newName)
Expand Down
2 changes: 1 addition & 1 deletion src/tracks/AutomationTrack.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ namespace lmms
AutomationTrack::AutomationTrack( TrackContainer* tc, bool _hidden ) :
Track( _hidden ? Type::HiddenAutomation : Type::Automation, tc )
{
setName( tr( "Automation track" ) );
setName(findUniqueName(tr("Automation track")));
}

bool AutomationTrack::play( const TimePos & time_start, const fpp_t _frames,
Expand Down
4 changes: 2 additions & 2 deletions src/tracks/InstrumentTrack.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ InstrumentTrack::InstrumentTrack( TrackContainer* tc ) :
this, [this, i]{ processCCEvent(i); }, Qt::DirectConnection);
}

setName( tr( "Default preset" ) );
setName(findUniqueName(tr("Default preset")));

connect(&m_baseNoteModel, SIGNAL(dataChanged()), this, SLOT(updateBaseNote()), Qt::DirectConnection);
connect(&m_pitchModel, SIGNAL(dataChanged()), this, SLOT(updatePitch()), Qt::DirectConnection);
Expand Down Expand Up @@ -1056,7 +1056,7 @@ Instrument * InstrumentTrack::loadInstrument(const QString & _plugin_name,
m_instrument = Instrument::instantiate(_plugin_name, this,
key, keyFromDnd);
unlock();
setName(m_instrument->displayName());
setName(findUniqueName(m_instrument->displayName()));

emit instrumentChanged();

Expand Down
4 changes: 1 addition & 3 deletions src/tracks/PatternTrack.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ PatternTrack::PatternTrack(TrackContainer* tc) :
int patternNum = s_infoMap.size();
s_infoMap[this] = patternNum;

setName(tr("Pattern %1").arg(patternNum));
setName(findUniqueName(tr("Pattern")));
Engine::patternStore()->createClipsForPattern(patternNum);
Engine::patternStore()->setCurrentPattern(patternNum);
Engine::patternStore()->updateComboBox();
Expand Down Expand Up @@ -194,8 +194,6 @@ void PatternTrack::loadTrackSpecificSettings(const QDomElement& _this)
{
Clip::copyStateTo(track->getClip(src), track->getClip(dst));
}
setName( tr( "Clone of %1" ).arg(
_this.parentNode().toElement().attribute( "name" ) ) );
}
else
{
Expand Down
2 changes: 1 addition & 1 deletion src/tracks/SampleTrack.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ SampleTrack::SampleTrack(TrackContainer* tc) :
m_audioPort(tr("Sample track"), true, &m_volumeModel, &m_panningModel, &m_mutedModel),
m_isPlaying(false)
{
setName(tr("Sample track"));
setName(findUniqueName(tr("Sample track")));
m_panningModel.setCenterValue(DefaultPanning);
m_mixerChannelModel.setRange(0, Engine::mixer()->numChannels()-1, 1);

Expand Down
Loading