const QStringList DataManager::DATA_DIR_SUFFIX = QStringList() << "*.D";
const QString DataManager::S_RES_DATAEXPORT("Error while exporting data to file");
const QString DataManager::S_RES_IMGEXPORT("Error while exporting graph to image");
+const std::string DataManager::S_SEQ_KEY_SINGLE_RUNS = "Single runs";
DataManager::DataManager(QObject* parent) :
QObject(parent),
- m_sequenceRejected(false),
+ m_prevSequenceKey(""),
m_exportRawDataDialog(DataFileExporter::supportedFormats()),
m_graphToImageExportDialog(ImageDrawer::supportedImageFormats())
{
- m_sequences.push_back(std::make_pair<const QString, std::shared_ptr<Sequence>>("Single runs", std::shared_ptr<Sequence>(new Sequence())));
- m_seqSelModel.setSequences(&m_sequences);
+ m_sequences[S_SEQ_KEY_SINGLE_RUNS] = std::shared_ptr<Sequence>(new Sequence());
+ m_seqSelModel.setSequences(allSequenceKeys());
m_sigNameCodec = QTextCodec::codecForName("ISO-8859-1");
}
enum class Choice { YESTOALL, NOTOALL, ASK };
Choice c = Choice::ASK;
- for (NameSequencePair& nsp : m_sequences) {
- const QString seqName = nsp.first;
- std::shared_ptr<Sequence> seq = nsp.second;
+ for (auto& s : m_sequences) {
+ const QString seqName = QString::fromStdString(s.first);
+ std::shared_ptr<Sequence> seq = s.second;
SingleRunsMap::const_iterator it = seq->begin();
while (it != seq->end()) {
/* Private functions */
+std::vector<std::string> DataManager::allSequenceKeys() const
+{
+ std::vector<std::string> keys;
+
+ keys.reserve(m_sequences.size());
+ for (auto& s : m_sequences)
+ keys.push_back(s.first);
+
+ return keys;
+}
+
void DataManager::generateIntegDataWriteList(DataFileExporter::WriteList& writeList, const std::shared_ptr<SingleRunData> sr, const std::vector<std::string> &keys)
{
for (const std::string& key : keys) {
}
}
-std::shared_ptr<Sequence> DataManager::sequenceByKey(const QString& key)
-{
- for (NameSequencePair p : m_sequences) {
- if (p.first.compare(key) == 0)
- return p.second;
- }
- return nullptr;
-}
-
-int DataManager::sequenceIdxByKey(const QString& key)
-{
- int idx = 0;
- for (NameSequencePair p : m_sequences) {
- if (p.first.compare(key) == 0)
- return idx;
- idx++;
- }
- return -1;
-}
-
Signal::Equipment DataManager::equipmentFromFiletype(HPCS_FileType filetype)
{
switch (filetype) {
void DataManager::onLoadSequence(const QString& dir)
{
QDir rootDir(dir);
- QString uniqueName;
+ std::string uniqueName;
int nameSuffix = 1;
bool isUnique = false;
std::shared_ptr<Sequence> nSeq(new Sequence());
}
/* Generate unique name for the sequence */
- uniqueName = rootDir.dirName();
+ uniqueName = rootDir.dirName().toStdString();
while (!isUnique) {
- for (const NameSequencePair& nsp : m_sequences) {
+
+ for (const auto& nsp : m_sequences) {
if (nsp.first.compare(uniqueName) == 0) {
if (nameSuffix == 1)
- uniqueName += QString("_1");
+ uniqueName += "_1";
else
- uniqueName.replace(uniqueName.length()-1, 1, QString::number(nameSuffix));
+ uniqueName.replace(uniqueName.length()-1, 1, std::to_string(nameSuffix));
nameSuffix++;
} else
isUnique = true;
}
}
- m_sequences.push_back(NameSequencePair(uniqueName, nSeq));
- m_seqSelModel.seqenceAdded();
-
- emit setActiveSequenceIndex(m_sequences.size()-1);
+ m_sequences[uniqueName] = nSeq;
+ m_seqSelModel.addSequence(uniqueName);
+ onSequenceSelected(QString::fromStdString(uniqueName));
}
void DataManager::onLoadSingleRun(const QString& str)
{
- QString uniqueName;
+ std::string uniqueName;
int nameSuffix = 1;
- std::shared_ptr<Sequence> srseq = m_sequences.at(0).second;
+ std::shared_ptr<Sequence> srseq = m_sequences[S_SEQ_KEY_SINGLE_RUNS];
QDir dir(str);
std::shared_ptr<SingleRunData> srdata = loadSingleRun(dir);
if (srdata == nullptr)
return;
/* Generate unique name for the single run data */
- uniqueName = dir.dirName();
- while (srseq->at(uniqueName.toStdString()) != nullptr) {
- Logger::log(Logger::Level::INFO, ME_SENDER_STR, "[" + uniqueName + "]: Already there, adjusting.");
+ uniqueName = dir.dirName().toStdString();
+ while (srseq->at(uniqueName) != nullptr) {
+ Logger::log(Logger::Level::INFO, ME_SENDER_STR, "[" + QString::fromStdString(uniqueName) + "]: Already there, adjusting.");
if (nameSuffix == 1) {
- uniqueName += QString("_1");
+ uniqueName += "_1";
} else {
- uniqueName.replace(uniqueName.length()-1, 1, QString::number(nameSuffix));
+ uniqueName.replace(uniqueName.length()-1, 1, std::to_string(nameSuffix));
}
nameSuffix++;
}
- //TODO: Rewrite to std::string completely
+ srseq->add(uniqueName, srdata);
+ srseq->setSelectedRun(uniqueName);
- srseq->add(uniqueName.toStdString(), srdata);
- srseq->setSelectedRun(uniqueName.toStdString());
- emit setActiveSequenceIndex(0);
+ if (srseq == m_activeSequence) {
+ m_singleSelModel.addSingleRun(uniqueName);
+ onSingleRunSelected(QString::fromStdString(uniqueName));
+ emit setActiveSingleRunKey(uniqueName);
+ } else
+ onSequenceSelected(QString::fromStdString(S_SEQ_KEY_SINGLE_RUNS));
}
void DataManager::onSaveChanges()
void DataManager::onSaveAllChanges()
{
- for (NameSequencePair& p : m_sequences) {
+ for (auto& p : m_sequences) {
std::shared_ptr<Sequence> s = p.second;
SingleRunsMap::iterator it = s->begin();
}
}
-void DataManager::onSequenceSelected(const QString& key)
+void DataManager::onSequenceClose(const QString& key)
{
- if (m_sequenceRejected) {
- m_sequenceRejected = false;
+ std::shared_ptr<Sequence> seq;
+ QString newKey;
+ std::string stdKey = key.toStdString();
+
+ if (stdKey.compare(S_SEQ_KEY_SINGLE_RUNS) == 0) {
+ Logger::log(Logger::Level::DEBUG, ME_SENDER_STR, __QFUNC__ + "\"Single runs\" cannot be removed");
+ return;
+ }
+
+ try {
+ seq = m_sequences.at(stdKey);
+ } catch (std::out_of_range) {
+ Logger::log(Logger::Level::ERROR, ME_SENDER_STR, __QFUNC__ + "[" + key + "]: No such sequence.");
return;
}
- m_activeSequence = sequenceByKey(key);
- if (m_activeSequence == nullptr) {
- Logger::log(Logger::Level::ERROR, ME_SENDER_STR, "[" + key + "]: No such sequence.");
- m_activeSequence = sequenceByKey(m_prevSequenceKey);
- m_sequenceRejected = true;
- emit setActiveSequenceIndex(sequenceIdxByKey(m_prevSequenceKey));
+ SequenceMap::const_iterator cit = m_sequences.cbegin();
+ while (cit != m_sequences.cend()) {
+ if (cit->first.compare(stdKey) == 0)
+ break;
+ cit++;
+ }
+ if (cit == m_sequences.cend()) {
+ Logger::log(Logger::Level::CRITICAL, ME_SENDER_STR, __QFUNC__ + "Sequence \"" + key + "\" is valid but the key was not found");
+ return;
+ }
+ /* Closed single run was the last in the sequence */
+ if (std::next(cit) == m_sequences.cend())
+ newKey = QString::fromStdString(std::prev(cit)->first);
+ else
+ newKey = QString::fromStdString(std::next(cit)->first);
+
+ m_sequences.erase(stdKey);
+ m_prevSequenceKey = "";
+ m_seqSelModel.setSequences(allSequenceKeys());
+ emit cleanDashboard();
+ onSequenceSelected(newKey);
+}
+
+void DataManager::onSequenceSelected(const QString& key)
+{
+ std::shared_ptr<Sequence> seq;
+ std::string stdKey = key.toStdString();
+
+ try {
+ seq = m_sequences.at(stdKey);
+ } catch (std::out_of_range) {
+ Logger::log(Logger::Level::ERROR, ME_SENDER_STR, __QFUNC__ + "[" + key + "]: No such sequence");
+ if (m_prevSequenceKey.compare("") != 0)
+ onSequenceSelected(QString::fromStdString(m_prevSequenceKey));
+ else
+ m_singleSelModel.setSingleRuns(std::vector<std::string>()); /* Make sure we empty the list of single runs */
return;
}
- if (m_activeSequence->count() < 1) {
- Logger::log(Logger::Level::ERROR, ME_SENDER_STR, "There are no runs in sequence [" + key + "].");
+ if (seq == m_activeSequence)
+ return;
+
+ if (seq->count() < 1) {
+ Logger::log(Logger::Level::ERROR, ME_SENDER_STR, __QFUNC__ + "There are no runs in sequence [" + key + "].");
QMessageBox::information(nullptr, "Data manager", "Sequence '" + key + "' does not contain any runs.");
/* Revert to previous sequence */
- m_activeSequence = sequenceByKey(m_prevSequenceKey);
- m_sequenceRejected = true;
- emit setActiveSequenceIndex(sequenceIdxByKey(m_prevSequenceKey));
+ if (m_prevSequenceKey.compare("") != 0)
+ onSequenceSelected(QString::fromStdString(m_prevSequenceKey));
+ else
+ m_singleSelModel.setSingleRuns(std::vector<std::string>()); /* Make sure we empty the list of single runs */
return;
}
- m_prevSequenceKey = key;
+ m_activeSequence = seq;
+ m_prevSequenceKey = stdKey;
m_singleSelModel.setSingleRuns(m_activeSequence->allRunKeys());
+ emit setActiveSequenceKey(stdKey);
+ onSingleRunSelected(QString::fromStdString(m_activeSequence->selectedRunKey()));
emit setActiveSingleRunKey(m_activeSequence->selectedRunKey());
}
void DataManager::onSingleRunSelected(const QString& key)
{
+ std::string stdKey = key.toStdString();
+
if (m_activeSequence == nullptr)
return;
- if (!m_activeSequence->setSelectedRun(key.toStdString())) {
- Logger::log(Logger::Level::ERROR, ME_SENDER_STR, "[" + key + "]: No such single run.");
+ if (!m_activeSequence->setSelectedRun(stdKey)) {
+ Logger::log(Logger::Level::ERROR, ME_SENDER_STR, __QFUNC__ + "[" + key + "]: No such single run.");
return;
}
}
emit setSingleRunInfo(srdata->methodName(), srdata->operatorName(), srdata->sampleInfo(), srdata->date().toString() +" "+ srdata->time().toString());
- Logger::log(Logger::Level::DEBUG, ME_SENDER_STR, "Single run changed.");
+ Logger::log(Logger::Level::DEBUG, ME_SENDER_STR, __QFUNC__ + "Single run changed.");
}
#include "metatypes.h"
typedef std::function<void (DataFileExporter::WriteList&, const std::shared_ptr<SingleRunData>, std::vector<std::string>&)> GeneratorFunc;
+typedef std::map<const std::string, std::shared_ptr<Sequence>> SequenceMap;
class DataManager : public QObject
{
SingleRunsSelectorModel* singleRunsSelectorModel() { return &m_singleSelModel; }
private:
+ std::vector<std::string> allSequenceKeys() const;
Signal::Equipment equipmentFromFiletype(HPCS_FileType filetype);
void generateIntegDataWriteList(DataFileExporter::WriteList& writeList, const std::shared_ptr<SingleRunData> sr, const std::vector<std::string>& keys);
void generateRawDataWriteList(DataFileExporter::WriteList& writeList, const std::shared_ptr<SingleRunData> sr, const std::vector<std::string>& keys);
Signal::YUnit yunitFromUnitStr(const char* str);
std::shared_ptr<Sequence> m_activeSequence;
- QString m_prevSequenceKey;
- QString m_prevSingleRunKey;
+ std::string m_prevSequenceKey;
SequenceSelectorModel m_seqSelModel;
- bool m_sequenceRejected;
SingleRunsSelectorModel m_singleSelModel;
QTextCodec* m_sigNameCodec;
- std::vector<NameSequencePair> m_sequences;
+ SequenceMap m_sequences;
DataFilesLoader m_dfl;
ExportRawDataDialog m_exportRawDataDialog;
static const QString S_RES_DATAEXPORT;
static const QString S_RES_IMGEXPORT;
+ static const std::string S_SEQ_KEY_SINGLE_RUNS;
signals:
void addToDashboard(SignalView* sw);
void cleanDashboard();
- void setActiveSequenceIndex(const int idx);
+ void setActiveSequenceKey(const std::string& key);
void setActiveSingleRunKey(const std::string& key);
void setSingleRunInfo(const QString& method, const QString& operatorname, const QString& sample, const QString& datetime);
void onLoadSingleRun(const QString& dir);
void onSaveChanges();
void onSaveAllChanges();
+ void onSequenceClose(const QString& key);
void onSequenceSelected(const QString& key);
void onSingleRunClose(const QString& key);
void onSingleRunSelected(const QString& key);
connect(ui->actionLoad_single_run, SIGNAL(triggered()), this, SLOT(onLoadSingleRun()));
connect(ui->actionLoad_sequence, SIGNAL(triggered()), this, SLOT(onLoadSequence()));
connect(ui->actionClose_single_run, SIGNAL(triggered()), this, SLOT(onCloseSingleRun()));
+ connect(ui->actionClose_sequence, SIGNAL(triggered()), this, SLOT(onCloseSequence()));
connect(ui->actionSave_changes, SIGNAL(triggered()), this, SLOT(onSaveChanges()));
connect(ui->actionSave_all_changes, SIGNAL(triggered()), this, SLOT(onSaveAllChanges()));
/* EXPORT menu */
/* HELP menu */
connect(ui->actionAbout, SIGNAL(triggered()), this, SLOT(onAboutAnyanka()));
/* RUN/SEQ cboxes*/
- connect(ui->qcbox_sequence, SIGNAL(currentIndexChanged(QString)), this, SLOT(onSequenceSelected(QString)));
- connect(ui->qcbox_singleRun, SIGNAL(currentIndexChanged(QString)), this, SLOT(onSingleRunSelected(QString)));
+ connect(ui->qcbox_sequence, SIGNAL(activated(QString)), this, SLOT(onSequenceSelected(QString)));
+ connect(ui->qcbox_singleRun, SIGNAL(activated(QString)), this, SLOT(onSingleRunSelected(QString)));
}
/* Public slots */
emit singleRunClose(ui->qcbox_singleRun->currentText());
}
-void MainWindow::onSetActiveSequenceIndex(const int idx)
+void MainWindow::onSetActiveSequenceKey(const std::string& key)
{
- if (ui->qcbox_sequence->currentIndex() == idx)
- emit onSequenceSelected(ui->qcbox_sequence->currentText());
- else
- ui->qcbox_sequence->setCurrentIndex(idx);
+ const SequenceSelectorModel* model = static_cast<const SequenceSelectorModel*>(ui->qcbox_sequence->model());
+ if (key.compare("") == 0)
+ ui->qcbox_sequence->setCurrentIndex(-1);
+
+ int idx = model->idxFromKey(key);
+ ui->qcbox_sequence->setCurrentIndex(idx);
}
void MainWindow::onSetActiveSingleRunKey(const std::string& key)
{
const SingleRunsSelectorModel* model = static_cast<const SingleRunsSelectorModel*>(ui->qcbox_singleRun->model());
+ if (key.compare("") == 0)
+ ui->qcbox_singleRun->setCurrentIndex(-1);
+
int idx = model->idxFromKey(key);
ui->qcbox_singleRun->setCurrentIndex(idx);
}
aa.exec();
}
+void MainWindow::onCloseSequence()
+{
+ emit sequenceClose(ui->qcbox_sequence->currentText());
+}
+
void MainWindow::onIntegrateBaselineSelected()
{
emit integrateBaselineMode();
public slots:
void onAddToDashboard(SignalView* sw);
void onCleanDashboard();
- void onSetActiveSequenceIndex(const int idx);
+ void onSetActiveSequenceKey(const std::string& key);
void onSetActiveSingleRunKey(const std::string& key);
void onSetSingleRunInfo(const QString& method, const QString& operatorname, const QString& sample, const QString& datetime);
private slots:
void onAboutAnyanka();
+ void onCloseSequence();
void onCloseSingleRun();
void onExportGraphToImage() { emit exportGraphToImage(); }
void onExportPeaks() { emit exportPeaks(); }
void loadSingleRun(const QString& dir);
void saveChanges();
void saveAllChanges();
+ void sequenceClose(const QString& str);
void sequenceSelected(const QString& str);
void singleRunClose(const QString& key);
void singleRunSelected(const QString& str);
<addaction name="actionLoad_sequence"/>
<addaction name="separator"/>
<addaction name="actionClose_single_run"/>
+ <addaction name="actionClose_sequence"/>
<addaction name="separator"/>
<addaction name="actionSave_changes"/>
<addaction name="actionSave_all_changes"/>
<string>Close single run</string>
</property>
</action>
+ <action name="actionClose_sequence">
+ <property name="text">
+ <string>Close sequence</string>
+ </property>
+ </action>
</widget>
<resources/>
<connections/>
mWin->setSequenceListModel(dMgr->sequenceSelectorModel());
mWin->setSingleRunsListModel(dMgr->singleRunsSelectorModel());
/* Default to no sequence on load */
- mWin->onSetActiveSequenceIndex(-1);
+ mWin->onSetActiveSequenceKey("");
/* Connect SIGNALS/SLOTS */
QObject::connect(dMgr.get(), SIGNAL(addToDashboard(SignalView*)), mWin.get(), SLOT(onAddToDashboard(SignalView*)));
QObject::connect(dMgr.get(), SIGNAL(cleanDashboard()), mWin.get(), SLOT(onCleanDashboard()));
- QObject::connect(dMgr.get(), SIGNAL(setActiveSequenceIndex(int)), mWin.get(), SLOT(onSetActiveSequenceIndex(int)));
+ QObject::connect(dMgr.get(), SIGNAL(setActiveSequenceKey(std::string)), mWin.get(), SLOT(onSetActiveSequenceKey(std::string)));
QObject::connect(dMgr.get(), SIGNAL(setActiveSingleRunKey(std::string)), mWin.get(), SLOT(onSetActiveSingleRunKey(std::string)));
QObject::connect(dMgr.get(), SIGNAL(setSingleRunInfo(QString,QString,QString,QString)), mWin.get(), SLOT(onSetSingleRunInfo(QString,QString,QString,QString)));
QObject::connect(mWin.get(), SIGNAL(exportGraphToImage()),dMgr.get(), SLOT(onExportGraphToImage()));
QObject::connect(mWin.get(), SIGNAL(loadSingleRun(QString)), dMgr.get(), SLOT(onLoadSingleRun(QString)));
QObject::connect(mWin.get(), SIGNAL(loadSequence(QString)), dMgr.get(), SLOT(onLoadSequence(QString)));
QObject::connect(mWin.get(), SIGNAL(sequenceSelected(QString)), dMgr.get(), SLOT(onSequenceSelected(QString)));
+ QObject::connect(mWin.get(), SIGNAL(sequenceClose(QString)), dMgr.get(), SLOT(onSequenceClose(QString)));
QObject::connect(mWin.get(), SIGNAL(singleRunClose(QString)), dMgr.get(), SLOT(onSingleRunClose(QString)));
QObject::connect(mWin.get(), SIGNAL(singleRunSelected(QString)), dMgr.get(), SLOT(onSingleRunSelected(QString)));
m_singleRuns.erase(m_singleRuns.find(key));
}
+void Sequence::removeAll()
+{
+ m_singleRuns.clear();
+}
+
std::shared_ptr<SingleRunData> Sequence::selectedRun()
{
if (m_selectedRunKey.compare("") == 0)
size_t count() const { return m_singleRuns.size(); }
SingleRunsMap::iterator end() { return m_singleRuns.end(); }
void remove(const std::string& key);
+ void removeAll();
std::string selectedRunKey() const { return m_selectedRunKey; }
std::shared_ptr<SingleRunData> selectedRun();
bool setSelectedRun(const std::string& key);
#include "sequenceselectormodel.h"
SequenceSelectorModel::SequenceSelectorModel(QObject* parent) :
- QAbstractListModel(parent),
- m_activeSequences(nullptr)
+ QAbstractListModel(parent)
{
}
-SequenceSelectorModel::SequenceSelectorModel(const std::vector<NameSequencePair>* sequences, QObject* parent) :
- QAbstractListModel(parent),
- m_activeSequences(sequences)
+void SequenceSelectorModel::addSequence(const std::string& key)
{
+ beginInsertRows(QModelIndex(), m_sequenceKeys.size(), m_sequenceKeys.size());
+ m_sequenceKeys.push_back(key);
+ endInsertRows();
}
QVariant SequenceSelectorModel::data(const QModelIndex& index, int role) const
int seqIdx = 0;
if (role != Qt::DisplayRole)
return QVariant();
- if (m_activeSequences == nullptr)
+ if (m_sequenceKeys.size() == 0)
return QVariant();
- std::vector<NameSequencePair>::const_iterator cit = m_activeSequences->cbegin();
- while (cit != m_activeSequences->cend()) {
+ for (const std::string& s : m_sequenceKeys) {
if (seqIdx == index.row())
- return cit->first;
- seqIdx++; cit++;
+ return QString::fromStdString(s);
+ seqIdx++;
}
+
return QVariant();
}
-int SequenceSelectorModel::rowCount(const QModelIndex& parent) const
+int SequenceSelectorModel::idxFromKey(const std::string& key) const
{
- Q_UNUSED(parent);
+ int idx = 0;
+ for (const std::string& s : m_sequenceKeys) {
+ if (s.compare(key) == 0) return idx;
+ else idx++;
+ }
- if (m_activeSequences == nullptr)
- return 0;
- else
- return m_activeSequences->size();
+ return -1;
}
-void SequenceSelectorModel::seqenceAdded()
+int SequenceSelectorModel::rowCount(const QModelIndex& parent) const
{
- beginInsertRows(QModelIndex(), m_activeSequences->size()-1, m_activeSequences->size()-1);
- endInsertRows();
+ Q_UNUSED(parent);
+
+ return m_sequenceKeys.size();
}
-void SequenceSelectorModel::setSequences(const std::vector<NameSequencePair>* sequences)
+void SequenceSelectorModel::setSequences(const std::vector<std::string> sequenceKeys)
{
beginResetModel();
- m_activeSequences = sequences;
+ m_sequenceKeys = sequenceKeys;
endResetModel();
}
#define SEQUENCESELECTORMODEL_H
#include "sequence.h"
-#include <mutex>
#include <QtCore/QAbstractListModel>
-typedef std::pair<const QString, std::shared_ptr<Sequence>> NameSequencePair;
-
class SequenceSelectorModel : public QAbstractListModel
{
public:
SequenceSelectorModel(QObject* parent = nullptr);
- SequenceSelectorModel(const std::vector<NameSequencePair>* sequences, QObject* parent = nullptr);
+ void addSequence(const std::string& key);
QVariant data(const QModelIndex& index, int role) const;
- void seqenceAdded();
int rowCount(const QModelIndex& parent) const;
- void setSequences(const std::vector<NameSequencePair>* sequence);
+ int idxFromKey(const std::string& key) const;
+ void setSequences(const std::vector<std::string> sequenceKeys);
private:
- const std::vector<NameSequencePair>* m_activeSequences;
+ std::vector<std::string> m_sequenceKeys;
};
#endif // SEQUENCESELECTORMODEL_H
{
}
+void SingleRunsSelectorModel::addSingleRun(const std::string& key)
+{
+ beginInsertRows(QModelIndex(), m_singleRunKeys.size(), m_singleRunKeys.size());
+ m_singleRunKeys.push_back(key);
+ endInsertRows();
+}
+
QVariant SingleRunsSelectorModel::data(const QModelIndex& index, int role) const
{
int runIdx = 0;
else idx++;
}
- /* if (idx == m_singleRunKeys.size())
- * Unknown key */
return -1;
}
Q_OBJECT
public:
explicit SingleRunsSelectorModel(QObject* parent = nullptr);
+ void addSingleRun(const std::string& key);
QVariant data(const QModelIndex& index, int role) const;
int idxFromKey(const std::string& key) const;
int rowCount(const QModelIndex& parent) const;