Rewrote FileListModel class to use a QHash map internally. This should speed-up the lookup, especially when adding a huge number of files.
This commit is contained in:
parent
5d69b91c5b
commit
b00b527897
@ -32,6 +32,7 @@
|
|||||||
|
|
||||||
#define EXPAND(STR) QString(STR).leftJustified(96, ' ')
|
#define EXPAND(STR) QString(STR).leftJustified(96, ' ')
|
||||||
#define CHECK_HDR(STR,NAM) (!(STR).compare((NAM), Qt::CaseInsensitive))
|
#define CHECK_HDR(STR,NAM) (!(STR).compare((NAM), Qt::CaseInsensitive))
|
||||||
|
#define MAKE_KEY(PATH) (QDir::fromNativeSeparators(PATH).toLower())
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
// Constructor & Destructor
|
// Constructor & Destructor
|
||||||
@ -68,10 +69,10 @@ QVariant FileListModel::data(const QModelIndex &index, int role) const
|
|||||||
switch(index.column())
|
switch(index.column())
|
||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
return m_fileList.at(index.row()).fileName();
|
return m_fileStore.value(m_fileList.at(index.row())).fileName();
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
return QDir::toNativeSeparators(m_fileList.at(index.row()).filePath());
|
return QDir::toNativeSeparators(m_fileStore.value(m_fileList.at(index.row())).filePath());
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return QVariant();
|
return QVariant();
|
||||||
@ -136,33 +137,28 @@ QVariant FileListModel::headerData(int section, Qt::Orientation orientation, int
|
|||||||
void FileListModel::addFile(const QString &filePath)
|
void FileListModel::addFile(const QString &filePath)
|
||||||
{
|
{
|
||||||
QFileInfo fileInfo(filePath);
|
QFileInfo fileInfo(filePath);
|
||||||
|
const QString key = MAKE_KEY(fileInfo.canonicalFilePath());
|
||||||
|
|
||||||
for(int i = 0; i < m_fileList.count(); i++)
|
if(!m_fileStore.contains(key))
|
||||||
{
|
{
|
||||||
if(m_fileList.at(i).filePath().compare(fileInfo.canonicalFilePath(), Qt::CaseInsensitive) == 0)
|
beginInsertRows(QModelIndex(), m_fileList.count(), m_fileList.count());
|
||||||
{
|
m_fileStore.insert(key, AudioFileModel(fileInfo.canonicalFilePath(), fileInfo.baseName()));
|
||||||
return;
|
m_fileList.append(key);
|
||||||
|
endInsertRows();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
beginResetModel();
|
|
||||||
m_fileList.append(AudioFileModel(fileInfo.canonicalFilePath(), fileInfo.baseName()));
|
|
||||||
endResetModel();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void FileListModel::addFile(const AudioFileModel &file)
|
void FileListModel::addFile(const AudioFileModel &file)
|
||||||
{
|
{
|
||||||
for(int i = 0; i < m_fileList.count(); i++)
|
const QString key = MAKE_KEY(file.filePath());
|
||||||
{
|
|
||||||
if(m_fileList.at(i).filePath().compare(file.filePath(), Qt::CaseInsensitive) == 0)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
beginResetModel();
|
if(!m_fileStore.contains(key))
|
||||||
m_fileList.append(file);
|
{
|
||||||
endResetModel();
|
beginInsertRows(QModelIndex(), m_fileList.count(), m_fileList.count());
|
||||||
|
m_fileStore.insert(key, file);
|
||||||
|
m_fileList.append(key);
|
||||||
|
endInsertRows();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FileListModel::removeFile(const QModelIndex &index)
|
bool FileListModel::removeFile(const QModelIndex &index)
|
||||||
@ -170,6 +166,7 @@ bool FileListModel::removeFile(const QModelIndex &index)
|
|||||||
if(index.row() >= 0 && index.row() < m_fileList.count())
|
if(index.row() >= 0 && index.row() < m_fileList.count())
|
||||||
{
|
{
|
||||||
beginResetModel();
|
beginResetModel();
|
||||||
|
m_fileStore.remove(m_fileList.at(index.row()));
|
||||||
m_fileList.removeAt(index.row());
|
m_fileList.removeAt(index.row());
|
||||||
endResetModel();
|
endResetModel();
|
||||||
return true;
|
return true;
|
||||||
@ -184,6 +181,7 @@ void FileListModel::clearFiles(void)
|
|||||||
{
|
{
|
||||||
beginResetModel();
|
beginResetModel();
|
||||||
m_fileList.clear();
|
m_fileList.clear();
|
||||||
|
m_fileStore.clear();
|
||||||
endResetModel();
|
endResetModel();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -216,15 +214,21 @@ AudioFileModel FileListModel::getFile(const QModelIndex &index)
|
|||||||
|
|
||||||
AudioFileModel &FileListModel::operator[] (const QModelIndex &index)
|
AudioFileModel &FileListModel::operator[] (const QModelIndex &index)
|
||||||
{
|
{
|
||||||
return m_fileList[index.row()];
|
const QString key = m_fileList.at(index.row());
|
||||||
|
return m_fileStore[key];
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FileListModel::setFile(const QModelIndex &index, const AudioFileModel &audioFile)
|
bool FileListModel::setFile(const QModelIndex &index, const AudioFileModel &audioFile)
|
||||||
{
|
{
|
||||||
if(index.row() >= 0 && index.row() < m_fileList.count())
|
if(index.row() >= 0 && index.row() < m_fileList.count())
|
||||||
{
|
{
|
||||||
|
const QString oldKey = m_fileList.at(index.row());
|
||||||
|
const QString newKey = MAKE_KEY(audioFile.filePath());
|
||||||
|
|
||||||
beginResetModel();
|
beginResetModel();
|
||||||
m_fileList.replace(index.row(), audioFile);
|
m_fileList.replace(index.row(), newKey);
|
||||||
|
m_fileStore.remove(oldKey);
|
||||||
|
m_fileStore.insert(newKey, audioFile);
|
||||||
endResetModel();
|
endResetModel();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -242,13 +246,15 @@ int FileListModel::exportToCsv(const QString &outFile)
|
|||||||
|
|
||||||
for(int i = 0; i < nFiles; i++)
|
for(int i = 0; i < nFiles; i++)
|
||||||
{
|
{
|
||||||
if(m_fileList.at(i).filePosition() > 0) havePosition = true;
|
AudioFileModel current = m_fileStore.value(m_fileList.at(i));
|
||||||
if(!m_fileList.at(i).fileName().isEmpty()) haveTitle = true;
|
|
||||||
if(!m_fileList.at(i).fileArtist().isEmpty()) haveArtist = true;
|
if(current.filePosition() > 0) havePosition = true;
|
||||||
if(!m_fileList.at(i).fileAlbum().isEmpty()) haveAlbum = true;
|
if(!current.fileName().isEmpty()) haveTitle = true;
|
||||||
if(!m_fileList.at(i).fileGenre().isEmpty()) haveGenre = true;
|
if(!current.fileArtist().isEmpty()) haveArtist = true;
|
||||||
if(m_fileList.at(i).fileYear() > 0) haveYear = true;
|
if(!current.fileAlbum().isEmpty()) haveAlbum = true;
|
||||||
if(!m_fileList.at(i).fileComment().isEmpty()) haveComment = true;
|
if(!current.fileGenre().isEmpty()) haveGenre = true;
|
||||||
|
if(current.fileYear() > 0) haveYear = true;
|
||||||
|
if(!current.fileComment().isEmpty()) haveComment = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!(haveTitle || haveArtist || haveAlbum || haveGenre || haveYear || haveComment))
|
if(!(haveTitle || haveArtist || haveAlbum || haveGenre || haveYear || haveComment))
|
||||||
@ -284,14 +290,15 @@ int FileListModel::exportToCsv(const QString &outFile)
|
|||||||
for(int i = 0; i < nFiles; i++)
|
for(int i = 0; i < nFiles; i++)
|
||||||
{
|
{
|
||||||
QStringList line;
|
QStringList line;
|
||||||
|
AudioFileModel current = m_fileStore.value(m_fileList.at(i));
|
||||||
|
|
||||||
if(havePosition) line << QString::number(m_fileList.at(i).filePosition());
|
if(havePosition) line << QString::number(current.filePosition());
|
||||||
if(haveTitle) line << m_fileList.at(i).fileName().trimmed();
|
if(haveTitle) line << current.fileName().trimmed();
|
||||||
if(haveArtist) line << m_fileList.at(i).fileArtist().trimmed();
|
if(haveArtist) line << current.fileArtist().trimmed();
|
||||||
if(haveAlbum) line << m_fileList.at(i).fileAlbum().trimmed();
|
if(haveAlbum) line << current.fileAlbum().trimmed();
|
||||||
if(haveGenre) line << m_fileList.at(i).fileGenre().trimmed();
|
if(haveGenre) line << current.fileGenre().trimmed();
|
||||||
if(haveYear) line << QString::number(m_fileList.at(i).fileYear());
|
if(haveYear) line << QString::number(current.fileYear());
|
||||||
if(haveComment) line << m_fileList.at(i).fileComment().trimmed();
|
if(haveComment) line << current.fileComment().trimmed();
|
||||||
|
|
||||||
if(file.write(line.replaceInStrings(";", ",").join(";").append("\r\n").toUtf8()) < 1)
|
if(file.write(line.replaceInStrings(";", ",").join(";").append("\r\n").toUtf8()) < 1)
|
||||||
{
|
{
|
||||||
@ -431,6 +438,8 @@ int FileListModel::importFromCsv(QWidget *parent, const QString &inFile)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const QString key = m_fileList[i];
|
||||||
|
|
||||||
for(int j = 0; j < nCols; j++)
|
for(int j = 0; j < nCols; j++)
|
||||||
{
|
{
|
||||||
if(ignore[j])
|
if(ignore[j])
|
||||||
@ -441,38 +450,38 @@ int FileListModel::importFromCsv(QWidget *parent, const QString &inFile)
|
|||||||
{
|
{
|
||||||
bool ok = false;
|
bool ok = false;
|
||||||
unsigned int temp = data.at(j).trimmed().toUInt(&ok);
|
unsigned int temp = data.at(j).trimmed().toUInt(&ok);
|
||||||
if(ok) m_fileList[i].setFilePosition(temp);
|
if(ok) m_fileStore[key].setFilePosition(temp);
|
||||||
}
|
}
|
||||||
else if(CHECK_HDR(header.at(j), "TITLE"))
|
else if(CHECK_HDR(header.at(j), "TITLE"))
|
||||||
{
|
{
|
||||||
QString temp = data.at(j).trimmed();
|
QString temp = data.at(j).trimmed();
|
||||||
if(!temp.isEmpty()) m_fileList[i].setFileName(temp);
|
if(!temp.isEmpty()) m_fileStore[key].setFileName(temp);
|
||||||
}
|
}
|
||||||
else if(CHECK_HDR(header.at(j), "ARTIST"))
|
else if(CHECK_HDR(header.at(j), "ARTIST"))
|
||||||
{
|
{
|
||||||
QString temp = data.at(j).trimmed();
|
QString temp = data.at(j).trimmed();
|
||||||
if(!temp.isEmpty()) m_fileList[i].setFileArtist(temp);
|
if(!temp.isEmpty()) m_fileStore[key].setFileArtist(temp);
|
||||||
}
|
}
|
||||||
else if(CHECK_HDR(header.at(j), "ALBUM"))
|
else if(CHECK_HDR(header.at(j), "ALBUM"))
|
||||||
{
|
{
|
||||||
QString temp = data.at(j).trimmed();
|
QString temp = data.at(j).trimmed();
|
||||||
if(!temp.isEmpty()) m_fileList[i].setFileAlbum(temp);
|
if(!temp.isEmpty()) m_fileStore[key].setFileAlbum(temp);
|
||||||
}
|
}
|
||||||
else if(CHECK_HDR(header.at(j), "GENRE"))
|
else if(CHECK_HDR(header.at(j), "GENRE"))
|
||||||
{
|
{
|
||||||
QString temp = data.at(j).trimmed();
|
QString temp = data.at(j).trimmed();
|
||||||
if(!temp.isEmpty()) m_fileList[i].setFileGenre(temp);
|
if(!temp.isEmpty()) m_fileStore[key].setFileGenre(temp);
|
||||||
}
|
}
|
||||||
else if(CHECK_HDR(header.at(j), "YEAR"))
|
else if(CHECK_HDR(header.at(j), "YEAR"))
|
||||||
{
|
{
|
||||||
bool ok = false;
|
bool ok = false;
|
||||||
unsigned int temp = data.at(j).trimmed().toUInt(&ok);
|
unsigned int temp = data.at(j).trimmed().toUInt(&ok);
|
||||||
if(ok) m_fileList[i].setFileYear(temp);
|
if(ok) m_fileStore[key].setFileYear(temp);
|
||||||
}
|
}
|
||||||
else if(CHECK_HDR(header.at(j), "COMMENT"))
|
else if(CHECK_HDR(header.at(j), "COMMENT"))
|
||||||
{
|
{
|
||||||
QString temp = data.at(j).trimmed();
|
QString temp = data.at(j).trimmed();
|
||||||
if(!temp.isEmpty()) m_fileList[i].setFileComment(temp);
|
if(!temp.isEmpty()) m_fileStore[key].setFileComment(temp);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -70,7 +70,8 @@ public slots:
|
|||||||
void addFile(const AudioFileModel &file);
|
void addFile(const AudioFileModel &file);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QList<AudioFileModel> m_fileList;
|
QList<QString> m_fileList;
|
||||||
|
QHash<QString, AudioFileModel> m_fileStore;
|
||||||
const QIcon m_fileIcon;
|
const QIcon m_fileIcon;
|
||||||
|
|
||||||
static bool checkArray(const bool *a, const bool val, size_t len);
|
static bool checkArray(const bool *a, const bool val, size_t len);
|
||||||
|
Loading…
Reference in New Issue
Block a user