/* 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. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "newmoviewizard.h" #include "smtreeitem.h" #include "seriestreemodel.h" #include "filestreemodel.h" #include "smglobals.h" #include "mappingtablewidget.h" #include "mappingtablemodel.h" #include "seriesmetadatamodel.h" #include "filestreemodel.h" #include "helper.h" #include "pictureviewer2.h" NewMovieWizard::NewMovieWizard(QWidget *parent) : QWizard(parent){ mInfoPage = new MovieInfoPage; mActorPage = new MovieMappingPage("actors"); mGenrePage = new MovieMappingPage("genres"); mMetadataPage = new MovieMetadataPage; addPage(mInfoPage); addPage(mActorPage); addPage(mGenrePage); addPage(mMetadataPage); setOption(QWizard::IndependentPages, true); } void NewMovieWizard::showEvent(QShowEvent *){ Helper::centerWidget(this); } void NewMovieWizard::accept(){ //conjure up models SeriesTreeModel *seriesModel = static_cast(SmGlobals::instance()->model("SeriesModel")); FilesTreeModel *filesModel = static_cast(SmGlobals::instance()->model("FilesModel")); //handle series QString series = field("title").toString(); bool hasPartNo = field("hasPartNo").toBool(); series = series.toLower().trimmed(); QModelIndex seriesIdx = seriesModel->find(series); if(!seriesIdx.isValid()){ if(seriesModel->addSeries(series, QModelIndex())){ seriesIdx = seriesModel->find(series); }else{ QMessageBox::critical(this, tr("Error"), tr("Failed to create new series!")); return; } } //handle seriespart QModelIndex seriesPartIdx; QString subTitle = field("subtitle").toString(); int seriesno = 0; if(hasPartNo){ seriesno = field("seriesNo").toInt(); seriesPartIdx = seriesModel->find(seriesno, SeriesTreeModel::SeriesPart, seriesIdx); }else{ seriesPartIdx = seriesModel->find(subTitle, SeriesTreeModel::Subtitle, seriesIdx); } if(seriesPartIdx.isValid()){ if(hasPartNo){ QString error = QString(tr("Already have part %1 of %2")).arg(seriesno).arg(series); QMessageBox::critical(this, tr("Error"), error); return; }else{ QString error = QString(tr("Already have a part with subtitle %1")).arg(seriesPartIdx.data(SeriesTreeModel::SubtitleRole).toString()); QMessageBox::critical(this, tr("Error"), error); return; } } if(!seriesModel->addSeriesPart(seriesno, seriesIdx, subTitle)){ QMessageBox::critical(this, tr("Error"), tr("Failed to create series part!")); return; } if(hasPartNo){ seriesPartIdx = seriesModel->find(seriesno, SeriesTreeModel::SeriesPart, seriesIdx); }else{ seriesPartIdx = seriesModel->find(subTitle, SeriesTreeModel::Subtitle, seriesIdx); } if(!seriesPartIdx.isValid()){ QMessageBox::critical(this, tr("Error"), tr("Strange. Could not find series part! Cowardly bailing out.")); return; } int seriesPartId = seriesPartIdx.data(SeriesTreeModel::SeriesPartIdRole).toInt(); //handle files MovieInfoPage *movieInfoPage = static_cast(page(0)); WizardTreeModel *wizardModel = movieInfoPage->model(); int quality = field("quality").toInt(); int dvdNo = -1; bool onDvd = field("onDvd").toBool(); if(onDvd){ dvdNo = field("dvdNo").toInt(); } QHash fileData = wizardModel->files(); QHash::const_iterator it = fileData.constBegin(); while(it != fileData.constEnd()){ QString path = it.key(); int type = it.value(); int partNo = wizardModel->filesPart(path); if(filesModel->addFile(path, type, quality, partNo, seriesPartId, dvdNo)){ QString md5sum = Helper::md5Sum(path); Helper::moveToArchive(path, md5sum); } ++it; } if(onDvd){ filesModel->addFile(tr("DVD"), FilesTreeModel::Movie, quality, -1, seriesPartId, dvdNo); } //handle actors MovieMappingPage *actorPage = static_cast(page(1)); MappingTableItemModel *actorItemModel = actorPage->model(); QStringList actors = actorItemModel->stringList(); MappingTableModel *actorModel = static_cast(SmGlobals::instance()->model("actors")); actorModel->setMappings(actors, seriesPartId); //handle genres MovieMappingPage *genrePage = static_cast(page(2)); MappingTableItemModel *genreItemModel = genrePage->model(); QStringList genres = genreItemModel->stringList(); MappingTableModel *genreModel = static_cast(SmGlobals::instance()->model("genres")); genreModel->setMappings(genres, seriesPartId); //handle metadata doMetadata(seriesPartIdx); //make picviewer setting persistent QSettings s; s.setValue("ui/archiveusepicviewer", field("usePicViewer")); //done emit seriesAdded(series, seriesno); QDialog::accept(); } void NewMovieWizard::doMetadata(const QModelIndex &idx){ bool isEnabled = field("enabled").toBool(); if(!isEnabled){ return; } int seriesPartId = idx.data(SeriesTreeModel::SeriesPartIdRole).toInt(); SeriesMetadataModel *metadataModel = static_cast(SmGlobals::instance()->model("SeriesMetadata")); metadataModel->populate(seriesPartId); QList metaData; for(int i = 0; i < metadataModel->numFields(); ++i){ metaData << QVariant(); } metaData[SeriesMetadataModel::ReleaseYear] = field("year"); metaData[SeriesMetadataModel::Subject] = field("subject"); metaData[SeriesMetadataModel::EncoderOpts] = field("encoder"); metaData[SeriesMetadataModel::Passes] = field("passes"); metaData[SeriesMetadataModel::SourceMedium] = mMetadataPage->sourceMedium(); metaData[SeriesMetadataModel::ReleaseGroup] = mMetadataPage->releaseGroup(); metaData[SeriesMetadataModel::Comment] = mMetadataPage->comment(); metaData[SeriesMetadataModel::Added] = QDate::currentDate(); metadataModel->setAllData(seriesPartId, metaData); } MovieInfoPage::MovieInfoPage(QWidget *parent) : QWizardPage(parent){ setupGui(); mPicViewer = SmGlobals::instance()->pictureViewer(); connect(mFileView, SIGNAL(clicked(QModelIndex)), this, SLOT(itemClicked(QModelIndex))); } void MovieInfoPage::setupGui(){ setTitle(tr("Collect files for movie")); setSubTitle(tr("Select files by clicking the \"Add files...\" button. After adding files select one by one and set the appropriate file type. The series no is the number the movie has in the series: 14 in case of e.g. rogue adventures 14. The part number only has to be set if the movie is split in several parts.")); setPixmap(QWizard::LogoPixmap, QPixmap(":/shemov.png")); //files model setup QStringList modelHeaders = QStringList() << tr("File name") << tr("Size") << tr("File Type") << tr("Part") << tr("Full path"); mFileModel = new WizardTreeModel(modelHeaders, this); initModel(); //files view mFileView = new QTreeView; mFileView->setModel(mFileModel); connect(mFileView->selectionModel(), SIGNAL(currentRowChanged(QModelIndex,QModelIndex)), this, SLOT(fileSelectionChanged(QModelIndex,QModelIndex))); mFileView->setAlternatingRowColors(true); //add + remove files QHBoxLayout *fileButtonLayout = new QHBoxLayout; fileButtonLayout->addStretch(); mAddFile = new QPushButton(tr("Add files...")); fileButtonLayout->addWidget(mAddFile); connect(mAddFile, SIGNAL(clicked()), this, SLOT(addFiles())); mRemoveFile = new QPushButton(tr("Remove file")); fileButtonLayout->addWidget(mRemoveFile); connect(mRemoveFile, SIGNAL(clicked()), this, SLOT(removeFile())); //movie name + subtitle QFormLayout *movieTitleLayout = new QFormLayout; mTitle = new QLineEdit; mSubtitle = new QLineEdit; movieTitleLayout->addRow(tr("Movie &title"), mTitle); movieTitleLayout->addRow(tr("Movie &subtitle"), mSubtitle); SeriesTreeModel *seriesModel = static_cast(SmGlobals::instance()->model("SeriesModel")); QCompleter *completer = new QCompleter(this); completer->setModel(seriesModel); mTitle->setCompleter(completer); //file type QHBoxLayout *numberLayout = new QHBoxLayout; QLabel *l2 = new QLabel(tr("File &type")); mFileType = new QComboBox; l2->setBuddy(mFileType); mFileType->addItems(mFileModel->types()); numberLayout->addWidget(l2); numberLayout->addWidget(mFileType); numberLayout->addStretch(); connect(mFileType, SIGNAL(currentIndexChanged(QString)), this, SLOT(typeChanged(QString))); //series, part + quality QLabel *l3 = new QLabel(tr("&Series no.")); mSeriesNo = new QSpinBox; l3->setBuddy(mSeriesNo); mSeriesNo->setMinimum(1); numberLayout->addWidget(l3); numberLayout->addWidget(mSeriesNo); QLabel *l4 = new QLabel(tr("&Part no.")); mPartno = new QSpinBox; l4->setBuddy(mPartno); mPartno->setMinimum(-1); connect(mPartno, SIGNAL(valueChanged(int)), this, SLOT(seriesPartChanged(int))); numberLayout->addWidget(l4); numberLayout->addWidget(mPartno); QLabel *l5 = new QLabel(tr("&Quality")); mQuality = new QSpinBox; l5->setBuddy(mQuality); mQuality->setMinimum(1); mQuality->setMaximum(10); numberLayout->addWidget(l5); numberLayout->addWidget(mQuality); //dvd QHBoxLayout *dvdLayout = new QHBoxLayout; mOnDvd = new QCheckBox(tr("Movie is on DVD")); dvdLayout->addWidget(mOnDvd); mHasPartno = new QCheckBox(tr("Movie has part no.")); mHasPartno->setChecked(true); connect(mHasPartno, SIGNAL(stateChanged(int)), this, SLOT(hasPartnoStateChanged(int))); dvdLayout->addWidget(mHasPartno); dvdLayout->addStretch(); QLabel *l6 = new QLabel(tr("Dvd no.")); dvdLayout->addWidget(l6); mDvdNo = new QSpinBox; mDvdNo->setMinimum(1); dvdLayout->addWidget(mDvdNo); connect(mOnDvd, SIGNAL(stateChanged(int)), this, SLOT(onDvd(int))); mNextDvdNo = new QPushButton(tr("Get next")); dvdLayout->addWidget(mNextDvdNo); connect(mNextDvdNo, SIGNAL(clicked()), this, SLOT(setNextDvdNo())); setNextDvdNo(); mNextDvdNo->setChecked(false); mDvdNo->setEnabled(false); mNextDvdNo->setEnabled(false); //picviewer QHBoxLayout *picViewerLayout = new QHBoxLayout; picViewerLayout->setAlignment(Qt::AlignRight | Qt::AlignHCenter); mUsePicViewer = new QCheckBox(tr("Use picture viewer when selecting item")); picViewerLayout->addWidget(mUsePicViewer); QSettings s; bool usePicViewer = s.value("ui/archiveusepicviewer", false).toBool(); mUsePicViewer->setChecked(usePicViewer); QVBoxLayout *mainLayout = new QVBoxLayout; mainLayout->addWidget(mFileView); mainLayout->addLayout(fileButtonLayout); mainLayout->addLayout(movieTitleLayout); mainLayout->addLayout(numberLayout); mainLayout->addLayout(dvdLayout); mainLayout->addLayout(picViewerLayout); setLayout(mainLayout); //expose data registerField("title*", mTitle); registerField("subtitle", mSubtitle); registerField("seriesNo", mSeriesNo); registerField("partNo", mPartno); registerField("quality", mQuality); registerField("dvdNo", mDvdNo); registerField("onDvd", mOnDvd); registerField("usePicViewer", mUsePicViewer); registerField("hasPartNo", mHasPartno); } void MovieInfoPage::initializePage(){ initModel(); mTitle->clear(); mSeriesNo->setValue(1); mPartno->setValue(1); mQuality->setValue(8); mOnDvd->setChecked(false); } void MovieInfoPage::addFile(const QString &file){ QFileInfo fi(file); if(fi.exists()){ QList itemData; QModelIndex parent = QModelIndex(); itemData << fi.fileName() << fi.size() << QVariant() << QVariant() << fi.absoluteFilePath(); QString mimeType = Helper::mimeType(fi.absoluteFilePath()); if(mimeType.startsWith("video")){ itemData[WizardTreeModel::FileType] = WizardTreeModel::Movie; parent = mFileModel->find("Movie files"); }else{ QString baseName = fi.completeBaseName(); QRegExp reFront = QRegExp("front"); reFront.setCaseSensitivity(Qt::CaseInsensitive); QRegExp reBack = QRegExp("back"); reBack.setCaseSensitivity(Qt::CaseInsensitive); if(baseName.endsWith('f') || (reFront.indexIn(baseName) != -1)){ itemData[WizardTreeModel::FileType] = WizardTreeModel::FrontCover; }else if(baseName.endsWith('b') || (reBack.indexIn(baseName) != -1)){ itemData[WizardTreeModel::FileType] = WizardTreeModel::BackCover; }else{ itemData[WizardTreeModel::FileType] = WizardTreeModel::GeneralCover; } parent = mFileModel->find("Cover files"); } if(parent.isValid()){ mFileModel->addRow(itemData, parent); } } mFileView->expandAll(); mFileView->resizeColumnToContents(0); mFileView->resizeColumnToContents(1); mFileView->resizeColumnToContents(2); } void MovieInfoPage::addFiles(){ QSettings s; QString startDir = s.value("paths/addfilespath", QDir::homePath()).toString(); QStringList files = QFileDialog::getOpenFileNames(this, tr("Select files"), startDir); if(files.isEmpty()){ return; } foreach(QString f, files){ addFile(f); } QFileInfo fi(files.at(0)); s.setValue("paths/addfilespath", fi.absolutePath()); } void MovieInfoPage::removeFile(){ QModelIndexList selected = mFileView->selectionModel()->selectedRows(); if(selected.isEmpty()){ return; } mFileModel->removeRows(selected.at(0).row(), 1, selected.at(0).parent()); } void MovieInfoPage::onDvd(int state){ mDvdNo->setEnabled(state == Qt::Checked); mNextDvdNo->setEnabled(state == Qt::Checked); } void MovieInfoPage::typeChanged(QString type){ QModelIndexList selected = mFileView->selectionModel()->selectedRows(); if(selected.isEmpty()){ return; } int newTypeId = mFileModel->typeId(type); if(newTypeId == -1){ return; } QModelIndex item = selected.at(0); QModelIndex typeIndex = mFileModel->index(item.row(), WizardTreeModel::FileType, item.parent()); QModelIndex oldParent = typeIndex.parent(); mFileModel->setData(typeIndex, newTypeId, Qt::EditRole); QModelIndex newParent; if(newTypeId == WizardTreeModel::Movie){ newParent = mFileModel->find("Movie files"); }else{ newParent = mFileModel->find("Cover files"); } if(oldParent != newParent){ mFileModel->reparent(item, newParent); } } void MovieInfoPage::seriesPartChanged(int partNo){ QModelIndexList selected = mFileView->selectionModel()->selectedRows(); if(selected.isEmpty()){ return; } QModelIndex item = selected.at(0); if(item.data(WizardTreeModel::FileTypeRole).toInt() == WizardTreeModel::Movie){ QModelIndex seriesPartIdx = mFileModel->index(item.row(), WizardTreeModel::FilePart, item.parent()); QVariant data = (partNo == 0) ? QVariant() : QVariant(partNo); mFileModel->setData(seriesPartIdx, data, Qt::EditRole); } } void MovieInfoPage::setNextDvdNo(){ SeriesTreeModel *seriesTreeModel = static_cast(SmGlobals::instance()->model("SeriesModel")); int nextdvd = seriesTreeModel->findNextDvdNo(); mDvdNo->setValue(nextdvd + 1); } void MovieInfoPage::initModel(){ SmTreeItem *root = new SmTreeItem(5); mMoviesItem= new SmTreeItem(QList() << tr("Movie files") << QVariant() << QVariant() << QVariant() << QVariant(), root); root->appendChild(mMoviesItem); mCoversItem = new SmTreeItem(QList() << tr("Cover files") << QVariant() << QVariant() << QVariant() << QVariant(), root); root->appendChild(mCoversItem); mFileModel->setRoot(root); } void MovieInfoPage::fileSelectionChanged(const QModelIndex ¤t, const QModelIndex &previous){ Q_UNUSED(previous); int type = current.data(WizardTreeModel::FileTypeRole).toInt(); if(type == WizardTreeModel::Movie){ int part = 1; QVariant filePart= current.data(WizardTreeModel::FilePartRole); if(filePart.isValid()){ part = filePart.toInt(); } mPartno->blockSignals(true); mPartno->setValue(part); mPartno->blockSignals(false); } QString typeString = mFileModel->typeName(type); int comboIdx = mFileType->findText(typeString); if(comboIdx != -1){ mFileType->blockSignals(true); mFileType->setCurrentIndex(comboIdx); mFileType->blockSignals(false); } } void MovieInfoPage::itemClicked(const QModelIndex &index){ if(!field("usePicViewer").toBool()){ return; } int type = index.data(WizardTreeModel::FileTypeRole).toInt(); switch(type){ case WizardTreeModel::Movie:{ QString framePath = SmGlobals::instance()->frameCache()->entryPath(index.data(WizardTreeModel::FullPathRole).toString(), QString()); mPicViewer->setFile(framePath); break; } case WizardTreeModel::FrontCover: case WizardTreeModel::BackCover: case WizardTreeModel::GeneralCover: mPicViewer->setFile(index.data(WizardTreeModel::FullPathRole).toString()); break; default: mPicViewer->setVisible(false); return; } mPicViewer->setVisible(true); mPicViewer->raise(); } void MovieInfoPage::hasPartnoStateChanged(int state){ mPartno->setEnabled(state == Qt::Checked); } MovieMappingPage::MovieMappingPage(const QString &table, QWidget *parent) : QWizardPage(parent){ QString title = QString(tr("Edit %1")).arg(table); QString subTitle = QString(tr("Edit %1 by adding them from the text field below")).arg(table); setTitle(title); setSubTitle(subTitle); mWidget = new MappingTableWidget(table); QHBoxLayout *mainLayout = new QHBoxLayout; mainLayout->addWidget(mWidget); setLayout(mainLayout); } void MovieMappingPage::initializePage(){ model()->setStringList(QStringList()); } MovieMetadataPage::MovieMetadataPage(QWidget *parent) : QWizardPage(parent){ setTitle(tr("Edit movie metadata")); setSubTitle(tr("Set the movie metadata here, as far as known")); mModel = static_cast(SmGlobals::instance()->model("SeriesMetadata")); setupGui(); } void MovieMetadataPage::setupGui(){ QFormLayout *rowLayout = new QFormLayout; mReleaseYear = new QSpinBox; mReleaseYear->setMaximum(3000); mReleaseYear->setMinimum(1900); rowLayout->addRow(tr("Release year"), mReleaseYear); mReleaseGroup = new QComboBox; mPasses = new QSpinBox; rowLayout->addRow(tr("Encoding passes"), mPasses); mReleaseGroup->setEditable(true); rowLayout->addRow(tr("Release group"), mReleaseGroup); mSourceMedium = new QComboBox; mSourceMedium->setEditable(true); rowLayout->addRow(tr("Source medium"), mSourceMedium); mSubject = new QLineEdit; rowLayout->addRow(tr("Usenet subject"), mSubject); mEncoderOpts = new QLineEdit; rowLayout->addRow(tr("Encoder options"), mEncoderOpts); QVBoxLayout *commentLayout = new QVBoxLayout; QLabel *commentLabel = new QLabel(tr("Comment")); commentLayout->addWidget(commentLabel); mComment = new QPlainTextEdit; commentLayout->addWidget(mComment); QHBoxLayout *enabledLayout = new QHBoxLayout; enabledLayout->setAlignment(Qt::AlignRight); mMetadataEnabled = new QCheckBox(tr("Enable metadata")); enabledLayout->addWidget(mMetadataEnabled); connect(mMetadataEnabled, SIGNAL(stateChanged(int)), this, SLOT(toggleMetadata(int))); mWidgets << mReleaseYear << mReleaseGroup << mSourceMedium << mSubject << mEncoderOpts << mComment << mPasses; toggleMetadata(Qt::Unchecked); QVBoxLayout *mainLayout = new QVBoxLayout; mainLayout->addLayout(rowLayout); mainLayout->addLayout(commentLayout); mainLayout->addLayout(enabledLayout); setLayout(mainLayout); //expose data registerField("year", mReleaseYear); registerField("passes", mPasses); registerField("group", mReleaseGroup); registerField("source", mSourceMedium); registerField("subject", mSubject); registerField("encoder", mEncoderOpts); registerField("comment", mComment); registerField("enabled", mMetadataEnabled); } void MovieMetadataPage::initializePage(){ QStringList relGroups = Helper::toStringList(mModel->fieldList(SeriesMetadataModel::ReleaseGroup)); mReleaseGroup->clear(); mReleaseGroup->addItems(relGroups); QStringList sourceMediums = Helper::toStringList(mModel->fieldList(SeriesMetadataModel::SourceMedium)); mSourceMedium->clear(); mSourceMedium->addItems(sourceMediums); mReleaseYear->setValue(QDate::currentDate().year()); mPasses->setValue(2); mSubject->clear(); mEncoderOpts->clear(); mComment->clear(); } QString MovieMetadataPage::comment() const { return mComment->toPlainText(); } QString MovieMetadataPage::releaseGroup() const { return mReleaseGroup->currentText(); } QString MovieMetadataPage::sourceMedium() const { return mSourceMedium->currentText(); } void MovieMetadataPage::toggleMetadata(int state){ bool isEnabled = (state == Qt::Checked); foreach(QWidget *w, mWidgets){ w->setEnabled(isEnabled); } } WizardTreeModel::WizardTreeModel(QStringList &headers, QObject *parent) : SmTreeModel(headers, parent){ FilesTreeModel *filesModel = static_cast(SmGlobals::instance()->model("FilesModel")); mFileTypeMap = filesModel->fileTypes(); } Qt::ItemFlags WizardTreeModel::flags(const QModelIndex &index) const{ if(!index.parent().isValid()){ return Qt::ItemIsEnabled; } return Qt::ItemIsEnabled | Qt::ItemIsSelectable; } QHash WizardTreeModel::files() { QHash retval; mFilePartMap.clear(); SmTreeItem *rootItem = root(); for(int i = 0; i < rootItem->childCount(); ++i){ SmTreeItem *firstChild = rootItem->child(i); for(int j = 0; j < firstChild->childCount(); ++j){ SmTreeItem *secondChild = firstChild->child(j); retval.insert(secondChild->data(WizardTreeModel::FullPath).toString(), secondChild->data(WizardTreeModel::FileType).toInt()); if(secondChild->data(WizardTreeModel::FilePart).isValid()){ mFilePartMap.insert(secondChild->data(WizardTreeModel::FullPath).toString(), secondChild->data(WizardTreeModel::FilePart).toInt()); } } } return retval; } int WizardTreeModel::filesPart(const QString &fullPath) const{ if(mFilePartMap.contains(fullPath)){ return mFilePartMap.value(fullPath); } return -1; } QVariant WizardTreeModel::data(const QModelIndex &index, int role) const{ SmTreeItem *item = static_cast(index.internalPointer()); if(role == Qt::DisplayRole){ if(index.column() == FileSize){ if(item->parent() == root()){ return QVariant(); } QLocale l; return l.toString(item->data(FileSize).toLongLong()); } if(index.column() == FileType){ return mFileTypeMap.value(item->data(FileType).toInt()); } return item->data(index.column()); } if(role == Qt::TextAlignmentRole){ if(index.column() == FileSize){ return Qt::AlignRight; } return Qt::AlignLeft; } if(role == FileNameRole){ return item->data(FileName); } if(role == FileSizeRole){ if(item->parent() == root()){ return QVariant(); } return item->data(FileSize); } if(role == FileTypeRole){ return item->data(FileType); } if(role == FullPathRole){ return item->data(FullPath); } if(role == FilePartRole){ return item->data(FilePart); } if(role == Qt::DecorationRole){ if(index.column() == 0){ QSettings s; bool iconizeCover = s.value("ui/iconizecovers", false).toBool(); if(iconizeCover){ int fileType = item->data(FileType).toInt(); if((fileType == FrontCover) || (fileType == BackCover) || (fileType == GeneralCover)){ return QIcon(item->data(FullPath).toString()); } } } return SmTreeModel::data(index, role); } return QVariant(); } QStringList WizardTreeModel::types() const { return mFileTypeMap.values(); } int WizardTreeModel::typeId(const QString &value) const{ QHash::const_iterator it = mFileTypeMap.constBegin(); while(it != mFileTypeMap.constEnd()){ if(it.value() == value){ return it.key(); } ++it; } return -1; } QString WizardTreeModel::typeName(int typeId) const{ return mFileTypeMap.value(typeId); }