/*========================================================================= medInria Copyright (c) INRIA 2013 - 2019. All rights reserved. See LICENSE.txt for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. =========================================================================*/ #include //#include // for setUri when medCore and medCoreLegacy will be fused medDataIndex::medDataIndex(int dataSourceId, int patientId, int studyId, int seriesId) : m_dataSourceId(dataSourceId), m_patientId(patientId), m_studyId(studyId), m_seriesId(seriesId) { } medDataIndex::medDataIndex(QStringList const & uri) : m_dataSourceId(NOT_VALID), m_patientId(NOT_VALID), m_studyId(NOT_VALID), m_seriesId(NOT_VALID), m_uriAsList(uri) { } medDataIndex::medDataIndex(QString const & uri) : m_dataSourceId(NOT_VALID), m_patientId(NOT_VALID), m_studyId(NOT_VALID), m_seriesId(NOT_VALID) { setUri(uri); } medDataIndex::medDataIndex(const medDataIndex& index) : m_dataSourceId(index.m_dataSourceId), m_patientId(index.m_patientId), m_studyId(index.m_studyId), m_seriesId(index.m_seriesId), m_uriAsList(index.m_uriAsList) { } medDataIndex::medDataIndex() : m_dataSourceId(NOT_VALID), m_patientId(NOT_VALID), m_studyId(NOT_VALID), m_seriesId(NOT_VALID) { } medDataIndex::~medDataIndex(void) { } bool medDataIndex::isV2() const { return !m_uriAsList.isEmpty(); } bool medDataIndex::isValid(void) const { return (m_dataSourceId != NOT_VALID && m_patientId != NOT_VALID) ^ !m_uriAsList.isEmpty(); } bool medDataIndex::isValidForPatient(void) const { return (m_dataSourceId != NOT_VALID && m_patientId != NOT_VALID); } bool medDataIndex::isValidForStudy(void) const { return (isValidForPatient() && (m_studyId != NOT_VALID)); } bool medDataIndex::isValidForSeries(void) const { return (isValidForStudy() && (m_seriesId != NOT_VALID)); } medDataIndex& medDataIndex::operator=(const medDataIndex& index) { m_dataSourceId = index.m_dataSourceId; m_patientId = index.m_patientId; m_studyId = index.m_studyId; m_seriesId = index.m_seriesId; m_uriAsList = index.m_uriAsList; return *this; } QString medDataIndex::asString() const { QString returnString; if (m_uriAsList.isEmpty()) { returnString = QString::number(m_dataSourceId) + " | " + QString::number(m_patientId) + " | " + QString::number(m_studyId) + " | " + QString::number(m_seriesId); } else { returnString = m_uriAsList[0] + ":"; if (!m_uriAsList.isEmpty()) { int i = 1; for (i = 1; i < m_uriAsList.size() - 1; ++i) { returnString += m_uriAsList[i] + "\r\n"; } returnString += m_uriAsList[i]; } } return returnString; } void medDataIndex::setUri(QString const & uri) { int sourceDelimterIndex = uri.indexOf(QString(":")); m_uriAsList = uri.right(uri.size() - sourceDelimterIndex-1).split(QString("\r\n")); m_uriAsList.push_front(uri.left(sourceDelimterIndex)); //m_uriAsList = medDataHub::uriAsList(uri); } /** * Returns true if two indexes match, where either input may be a patient, study or series. * Here, NOT_VALID on either side is treated as equality where operator== requires values that are equal. */ bool medDataIndex::isMatch( const medDataIndex& index1, const medDataIndex& index2) { if (index1.m_uriAsList.isEmpty() && index2.m_uriAsList.isEmpty()) { if (index1.dataSourceId() != index2.dataSourceId()) return false; if (index1.patientId() == NOT_VALID || index2.patientId() == NOT_VALID) return true; if (index1.patientId() != index2.patientId()) return false; if (index1.studyId() == NOT_VALID || index2.studyId() == NOT_VALID) return true; if (index1.studyId() != index2.studyId()) return false; if (index1.seriesId() == NOT_VALID || index2.seriesId() == NOT_VALID) return true; if (index1.seriesId() != index2.seriesId()) return false; return true; // patient, study, and series match and are not -1; } else { return index1.m_uriAsList == index2.m_uriAsList; } } /** Create mime representation. Caller takes ownership of the pointer.*/ QMimeData * medDataIndex::createMimeData() { QString indexString = QString("%1:%2:%3:%4").arg(this->dataSourceId()) .arg(this->patientId()) .arg(this->studyId()).arg(this->seriesId()); QMimeData *data = new QMimeData; if (m_uriAsList.isEmpty()) { data->setData("med/index", indexString.toLatin1()); } else { data->setData("med/index2", asString().toUtf8()); } return data; } /** Read medDataIndex from mime data. Returns an invalid index in case of error.*/ medDataIndex medDataIndex::readMimeData( const QMimeData * mimeData ) { if (mimeData->hasFormat("med/index")) { QStringList ids = QString(mimeData->data("med/index")).split(":"); if ( ids.size() >= 4 ) { int intIds[4]; bool allOk = true; for ( int i(0); i<4; ++i ) { bool ok = false; intIds[i] = ids.at(i).toInt(&ok); if ( !ok ) { allOk = false; break; } } if (allOk) { return medDataIndex( intIds[0], intIds[1], intIds[2], intIds[3] ); } } } else if (mimeData->hasFormat("med/index2")) { medDataIndex dataIndexRes; dataIndexRes.setUri(QString::fromUtf8(mimeData->data("med/index2"))); return dataIndexRes; } return medDataIndex(); } QList medDataIndex::readMimeDataMulti(const QMimeData * mimeData) { QList dataIndexListRes; auto rawData = mimeData->data("med/index2"); if (!rawData.isEmpty()) { auto uris = rawData.split('\0'); for (auto uri : uris) { medDataIndex dataIndexTmp; dataIndexTmp.setUri(QString::fromUtf8(uri)); dataIndexListRes << dataIndexTmp; } } return dataIndexListRes; } medDataIndex medDataIndex::makePatientIndex(int sourceId, int patientId ) { return medDataIndex(sourceId, patientId, NOT_VALID, NOT_VALID); } medDataIndex medDataIndex::makeStudyIndex( int sourceId, int patientId, int studyId ) { return medDataIndex(sourceId, patientId, studyId, NOT_VALID); } medDataIndex medDataIndex::makeSeriesIndex( int sourceId, int patientId, int studyId, int seriesId ) { return medDataIndex(sourceId, patientId, studyId, seriesId); } //QModelIndex medDataIndex::toModelIndex() const //{ // //} // ///////////////////////////////////////////////////////////////// // Convenience operators // ///////////////////////////////////////////////////////////////// bool operator==(const medDataIndex& index1, const medDataIndex& index2) { bool bRes = false; if (!(index1.isV2() ^ index2.isV2())) { if (!index1.isV2()) { bRes = (index1.dataSourceId() == index2.dataSourceId()) && (index1.patientId() == index2.patientId()) && (index1.studyId() == index2.studyId()) && (index1.seriesId() == index2.seriesId()); } else { bRes = !index1.m_uriAsList.isEmpty() && (index1.m_uriAsList == index2.m_uriAsList); } } return bRes; } bool operator!=(const medDataIndex& index1, const medDataIndex& index2) { return (!operator==(index1, index2)); } QDebug operator<<(QDebug debug, const medDataIndex& index) { debug.nospace() << "(" << index.m_dataSourceId << ", " << index.m_patientId << ", " << index.m_studyId << ", " << index.m_seriesId << ", " << index.m_uriAsList << ")"; return debug.space(); } QDebug operator<<(QDebug debug, medDataIndex *index) { if ( index ) { debug << *index; } else { debug.nospace() << "(" << "[medDataIndex* null]" << ")"; } return debug.space(); } /** * The less than operator can be used with STL maps. * Ordering is by patientId, then studyId, then seriesId. */ bool operator<(const medDataIndex& index1, const medDataIndex& index2) { if (index1.m_uriAsList.isEmpty()) { if (index1.dataSourceId() < index2.dataSourceId()) return true; else if (index2.dataSourceId() < index1.dataSourceId()) return false; else if (index1.patientId() < index2.patientId()) return true; else if (index2.patientId() < index1.patientId()) return false; else if (index1.studyId() < index2.studyId()) return true; else if (index2.studyId() < index1.studyId()) return false; else if (index1.seriesId() < index2.seriesId()) return true; else if (index2.seriesId() < index1.seriesId()) return false; } else { return index1.m_uriAsList < index2.m_uriAsList; } // if we reach here, either greater or equal, return false return false; } // ///////////////////////////////////////////////////////////////// // Hash functions // ///////////////////////////////////////////////////////////////// uint qHash(const medDataIndex &key) { uint hash = 0; if (key.uri().isEmpty()) { hash = hash ^ qHash(key.dataSourceId()); hash = hash ^ qHash(key.patientId()); hash = hash ^ qHash(key.studyId()); hash = hash ^ qHash(key.seriesId()); } else { hash = hash ^ qHash(key.uri()); } return hash; }