/* 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 "archiveview.h" #include "archivecontroller.h" #include "mappingtablewidget.h" #include "delegates.h" #include "smglobals.h" #include "helper.h" ArchiveView::ArchiveView(QWidget *parent) : QWidget(parent) { QSettings s; mArchiveModel = static_cast(SmGlobals::instance()->model("ArchiveModel")); connect(mArchiveModel, SIGNAL(needRefresh()), this, SLOT(refreshArchive())); connect(mArchiveModel, SIGNAL(databaseError(QString)), this, SLOT(showDatabaseError(QString))); mProxy = new ArchiveProxy; mProxy->setSourceModel(mArchiveModel); mTree = new ArchiveTree; mTree->setModel(mProxy); mTree->setColumnHidden(ArchiveModel::GenericId, true); mTree->setColumnHidden(ArchiveModel::SeriesPartId, true); mTree->setColumnHidden(ArchiveModel::SeriesPart, true); mTree->setColumnHidden(ArchiveModel::Type, true); mTree->setColumnHidden(ArchiveModel::Favorite, true); mTree->setColumnHidden(ArchiveModel::Subtitle, true); mTree->setColumnHidden(ArchiveModel::Count, true); mTree->resizeColumnToContents(ArchiveModel::Name); mTree->setSortingEnabled(true); mTree->setEditTriggers(QAbstractItemView::NoEditTriggers); connect(mTree, SIGNAL(expanded(QModelIndex)), this, SLOT(expandItem(QModelIndex))); connect(mTree, SIGNAL(collapsed(QModelIndex)), this, SLOT(collapseItem(QModelIndex))); QString sortOrderName = s.value("archivemodel/sortorder", "Series Name").toString(); mSortOrder = new QComboBox; mSortOrder->addItems(mArchiveModel->availableOrders()); mSortOrder->setCurrentText(sortOrderName); // this is _not_ redundant! when sortOrderName is the first // item in the list, nothing will happen otherwise! mArchiveModel->setOrder(sortOrderName); connect(mSortOrder, SIGNAL(currentIndexChanged(QString)), mArchiveModel, SLOT(setOrder(QString))); connect(mArchiveModel, SIGNAL(modelReset()), this, SLOT(doSelection())); QLabel *l1 = new QLabel(tr("Filter")); mFilter = new QLineEdit; QString savedFilter = s.value("archivemodel/filter", QString()).toString(); connect(mFilter, SIGNAL(returnPressed()), this, SLOT(setFilter())); QPushButton *filter = new QPushButton(tr("Filter")); connect(filter, SIGNAL(clicked()), this, SLOT(setFilter())); QPushButton *clear = new QPushButton(tr("Clear")); mFilter->setText(savedFilter); connect(clear, SIGNAL(clicked()), this, SLOT(clearFilter())); mProxy->setFilter(savedFilter, currentSortOrder()); QHBoxLayout *filterLayout = new QHBoxLayout; filterLayout->addWidget(l1); filterLayout->addWidget(mFilter); filterLayout->addWidget(filter); filterLayout->addWidget(clear); QVBoxLayout *treeLayout = new QVBoxLayout; treeLayout->addWidget(mSortOrder); treeLayout->addLayout(filterLayout); treeLayout->addWidget(mTree); QWidget *treeWidget = new QWidget; treeWidget->setLayout(treeLayout); mFiles = new ArchiveFiles; mFiles->setItemDelegateForColumn(ArchiveFilesModel::FileType, new FileTypeDelegate(this)); mFiles->setItemDelegateForColumn(ArchiveFilesModel::DvdNo, new DvdNoDelegate(this)); mFiles->setItemDelegateForColumn(ArchiveFilesModel::Size, new SizeDelegate(this)); mFiles->setItemDelegateForColumn(ArchiveFilesModel::SizeDur, new DurationDelegate(this)); mFiles->setItemDelegateForColumn(ArchiveFilesModel::FileNumber, new EmptyDelegate(this)); mFiles->setSelectionMode(QAbstractItemView::ExtendedSelection); mFiles->setSelectionBehavior(QAbstractItemView::SelectRows); mFilesModel = new ArchiveFilesModel(QStringList() << QChar(0x26A7) << tr("Seriespartid") << tr("Filename") << tr("Md5Sum") << tr("Size") << tr("Dvd") << tr("Type") << tr("No") << tr("Q") << tr("Fileid") << tr("S/Dur") << tr("Full Path"), this); mFilesProxy = new ArchiveFilesProxy; mFilesProxy->setSourceModel(mFilesModel); mFiles->setModel(mFilesProxy); QHBoxLayout *bottomRightLayout = new QHBoxLayout; mActorView = new SmTreeView; mActorView->setHeaderHidden(true); mActorModel = new QStandardItemModel(this); mActorView->setModel(mActorModel); QGroupBox *actorBox = new QGroupBox(tr("Actors")); QHBoxLayout *actorLayout = new QHBoxLayout; actorLayout->addWidget(mActorView); actorBox->setLayout(actorLayout); mGenreView = new SmTreeView; mGenreView->setHeaderHidden(true); mGenreModel = new QStandardItemModel(this); mGenreView->setModel(mGenreModel); QGroupBox *genreBox = new QGroupBox(tr("Genres")); QHBoxLayout *genreLayout = new QHBoxLayout; genreLayout->addWidget(mGenreView); genreBox->setLayout(genreLayout); mMetadataView = new QTextEdit; mMetadataView->setReadOnly(true); QGroupBox *metadataBox = new QGroupBox("Metadata"); QHBoxLayout *metadataLayout = new QHBoxLayout; metadataLayout->addWidget(mMetadataView); metadataBox->setLayout(metadataLayout); bottomRightLayout->addWidget(actorBox); bottomRightLayout->addWidget(genreBox); bottomRightLayout->addWidget(metadataBox); QVBoxLayout *rightLayout = new QVBoxLayout; rightLayout->addWidget(mFiles); rightLayout->addLayout(bottomRightLayout); QWidget *rightWidget = new QWidget; rightLayout->setStretchFactor(mFiles, 3); rightWidget->setLayout(rightLayout); mTreeSplitter = new QSplitter(Qt::Horizontal); mTreeSplitter->addWidget(treeWidget); mTreeSplitter->addWidget(rightWidget); mTreeSplitter->setStretchFactor(0, 1); mTreeSplitter->setStretchFactor(1, 4); QHBoxLayout *mainLayout = new QHBoxLayout; mainLayout->addWidget(mTreeSplitter); setLayout(mainLayout); initController(); } int ArchiveView::currentSortOrder() const { return mArchiveModel->availableOrdersHash().value(mSortOrder->currentText()); } void ArchiveView::readSettings(){ QSettings s; QVariantList list; list = s.value("archivemodel/expandedgenres").toList(); mExpandedItems[ArchiveModel::Genre] = list; list = s.value("archivemodel/expandedactors").toList(); mExpandedItems[ArchiveModel::Actor] = list; list = s.value("archivemodel/expandedseries").toList(); mExpandedItems[ArchiveModel::SeriesName] = list; mCurrentArchivePath = s.value("archivemodel/selectedseries").toStringList(); QByteArray splitterState = s.value("archivemodel/vsplitter").toByteArray(); mTreeSplitter->restoreState(splitterState); doSelection(); mFiles->readHeaderConfig(); mFiles->setSortingEnabled(true); } void ArchiveView::writeSettings() { QSettings s; s.setValue("archivemodel/sortorder", mSortOrder->currentText()); s.setValue("archivemodel/filter", mFilter->text()); s.setValue("archivemodel/expandedgenres", mExpandedItems.value(ArchiveModel::Genre)); s.setValue("archivemodel/expandedactors", mExpandedItems.value(ArchiveModel::Actor)); s.setValue("archivemodel/expandedseries", mExpandedItems.value(ArchiveModel::SeriesName)); s.setValue("archivemodel/selectedseries", mCurrentArchivePath); s.setValue("archivemodel/vsplitter", mTreeSplitter->saveState()); mFiles->writeHeaderConfig(); } void ArchiveView::refreshArchive(){ writeSettings(); mArchiveModel->refresh(); doSelection(); } void ArchiveView::doSelection(){ QVariantList list = mExpandedItems.value(currentSortOrder()); foreach(QVariant p, list){ QStringList path = p.toStringList(); QModelIndexList expand = mArchiveModel->pathToIndex(path); foreach(QModelIndex idx, expand){ mTree->setExpanded(mProxy->mapFromSource(idx), true); } } if(!mCurrentArchivePath.isEmpty()){ QModelIndexList l = mArchiveModel->pathToIndex(mCurrentArchivePath); if(!l.isEmpty()){ QModelIndex sel = mProxy->mapFromSource(l.last()); mTree->selectionModel()->select(sel, QItemSelectionModel::Rows | QItemSelectionModel::ClearAndSelect); } } } void ArchiveView::setFilter(){ QString filter = mFilter->text(); mProxy->setFilter(filter, currentSortOrder()); mTree->expandAll(); } void ArchiveView::clearFilter(){ mFilter->clear(); mProxy->setFilter(QString(), currentSortOrder()); mTree->collapseAll(); } void ArchiveView::showDatabaseError(const QString &errorMsg){ QMessageBox::critical(this, tr("Database Error"), errorMsg); } void ArchiveView::expandItem(const QModelIndex &idx){ QModelIndex realIdx = mProxy->mapToSource(idx); if(realIdx.isValid()){ QStringList path = mArchiveModel->indexToPath(realIdx); QVariantList list = mExpandedItems.value(currentSortOrder()); if(!list.contains(path)){ list << mArchiveModel->indexToPath(realIdx); } mExpandedItems[currentSortOrder()] = list; } } void ArchiveView::collapseItem(const QModelIndex &idx){ QModelIndex realIdx = mProxy->mapToSource(idx); if(realIdx.isValid()){ QVariantList list = mExpandedItems.value(currentSortOrder()); list.removeAll(mArchiveModel->indexToPath(realIdx)); mExpandedItems[currentSortOrder()] = list; } } void ArchiveView::initController(){ mController = new ArchiveController(this); mController->setArchiveView(this); mController->setArchiveTree(mTree, mProxy); mController->setArchiveFiles(mFiles, mFilesProxy); mController->setModels(mArchiveModel, mFilesModel); mController->setMappingModels(mActorModel, mGenreModel); mController->setMetadata(mMetadataView); mController->init(); SmGlobals::instance()->setArchiveController(mController); } ArchiveTree::ArchiveTree(QWidget *parent) : SmTreeView(parent) {} void ArchiveTree::setModel(ArchiveProxy *model){ mProxy = model; mModel = qobject_cast(mProxy->sourceModel()); QTreeView::setModel(model); } void ArchiveTree::edit(){ QModelIndex idx = firstSelected(); if(idx.isValid()){ QString currentName = idx.data(ArchiveModel::NameRole).toString(); QString question = QString(tr("Rename %1 to:")).arg(currentName); QString newName = QInputDialog::getText(this, tr("Rename"), question, QLineEdit::Normal, currentName); if(!newName.isEmpty()){ QModelIndex realIdx = mProxy->mapToSource(idx); mModel->setData(realIdx, newName, Qt::EditRole); } } } void ArchiveTree::remove(){ QModelIndex idx = firstSelected(); if(idx.isValid()){ QString warningMsg = QString("Really remove %1?").arg(idx.data().toString()); int retval = QMessageBox::warning(this, tr("Question"), warningMsg, QMessageBox::Yes | QMessageBox::No); if(retval == QMessageBox::Yes){ QModelIndex realIdx = mProxy->mapToSource(idx); if(!mModel->removeNode(realIdx)){ impossible(); } } } } void ArchiveTree::editActors(){ MappingEditor e(tr("Actors"), this); QStringList actors = mModel->allActors(); e.widget()->fillCompleter(actors); QModelIndex idx = firstSelected(); if(!idx.isValid()){ return; } int pId = idx.data(ArchiveModel::SeriesPartIdRole).toInt(); QStringList curActors = mModel->actors(QSet() << pId); e.widget()->setDecorationItem(SmGlobals::instance()->iconFor("actor")); e.widget()->setCurrentItems(curActors); int res = e.exec(); if(res == QDialog::Accepted){ QStringList selActors = e.widget()->items(); mModel->setActors(pId, selActors); ArchiveController *c = SmGlobals::instance()->archiveController(); c->treeSelectionChanged(QItemSelection(), QItemSelection()); } } void ArchiveTree::editGenres(){ MappingEditor e(tr("Genres"), this); QStringList genres = mModel->allGenres(); e.widget()->fillCompleter(genres); QModelIndex idx = firstSelected(); if(!idx.isValid()){ return; } int pId = idx.data(ArchiveModel::SeriesPartIdRole).toInt(); QStringList curGenres = mModel->genres(QSet() << pId); e.widget()->setDecorationItem(SmGlobals::instance()->iconFor("genre")); e.widget()->setCurrentItems(curGenres); int res = e.exec(); if(res == QDialog::Accepted){ QStringList selGenres = e.widget()->items(); mModel->setGenres(pId, selGenres); ArchiveController *c = SmGlobals::instance()->archiveController(); c->treeSelectionChanged(QItemSelection(), QItemSelection()); } } void ArchiveTree::editMetadata(){ QModelIndex idx = firstSelected(); if(!idx.isValid()){ return; } MetadataEditor e(this); ArchiveController *c = SmGlobals::instance()->archiveController(); QStringList sources = c->archiveTreeModel()->allSources(); e.widget()->setSources(sources); QStringList relGroups = c->archiveTreeModel()->allReleaseGroups(); e.widget()->setReleaseGroups(relGroups); int pId = idx.data(ArchiveModel::SeriesPartIdRole).toInt(); QList curMetadata = c->archiveTreeModel()->metadataList(pId); e.widget()->setMetadata(curMetadata); int res = e.exec(); if(res == QDialog::Accepted){ QList data = e.widget()->metadata(); mModel->setMetadata(pId, data); c->treeSelectionChanged(QItemSelection(), QItemSelection()); } } void ArchiveTree::editSeriesPart(){ QModelIndex idx = firstSelected(); if(!idx.isValid()){ return; } int curPart = idx.data(ArchiveModel::SeriesPartRole).toInt(); QString subtitle = idx.data(ArchiveModel::SubtitleRole).toString(); PartEditor e(this); e.setPartNo(curPart); e.setSubtitle(subtitle); int res = e.exec(); if(res == QDialog::Accepted){ int pId = idx.data(ArchiveModel::SeriesPartIdRole).toInt(); ArchiveController *c = SmGlobals::instance()->archiveController(); c->archiveTreeModel()->setPartNo(pId, e.partNo(), e.subtitle()); mModel->refresh(); } } void ArchiveTree::impossible(const QString msg){ QMessageBox::critical(this, tr("Error"), msg); } QModelIndex ArchiveTree::firstSelected(){ QModelIndexList idxs = selectionModel()->selectedRows(); if(idxs.isEmpty()){ QModelIndex(); } return idxs.first(); } ArchiveFiles::ArchiveFiles(const QString &headerSettings, QWidget *parent) : SmTreeView(headerSettings, parent){ setEditTriggers(QAbstractItemView::NoEditTriggers); } ArchiveProxy::ArchiveProxy(QObject *parent) : QSortFilterProxyModel(parent) {} void ArchiveProxy::setFilter(const QString &filter, int sortOrder){ mFilter = QRegExp(filter); mSortOrder = sortOrder; invalidateFilter(); } bool ArchiveProxy::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const { if(mFilter.isEmpty()){ return true; } QModelIndex nameIdx = sourceModel()->index(sourceRow, ArchiveModel::Name, sourceParent); ArchiveModel *model = qobject_cast(sourceModel()); return model->matchRecursive(nameIdx, mFilter); } ArchiveFilesProxy::ArchiveFilesProxy(QObject *parent) : QSortFilterProxyModel(parent) {} /* Mapping Editor Widget */ MappingEditorWidget::MappingEditorWidget(const QString &caption, QWidget *parent) : QWidget(parent), mCaption(caption){ // the view mModel = new QStandardItemModel(this); mModel->setHorizontalHeaderItem(0, new QStandardItem(mCaption)); mProxy = new QSortFilterProxyModel(this); mProxy->setSourceModel(mModel); QVBoxLayout *viewLayout = new QVBoxLayout; mView = new SmTreeView; viewLayout->addWidget(mView); mView->setModel(mProxy); mView->setSortingEnabled(true); // line editor QHBoxLayout *editLayout = new QHBoxLayout; QLabel *l2 = new QLabel(tr("Add:")); mEditor = new QLineEdit; mCompleter = new QCompleter(this); mCompleterModel = new QStringListModel(this); mCompleter->setModel(mCompleterModel); mEditor->setCompleter(mCompleter); editLayout->addWidget(l2); editLayout->addWidget(mEditor); // edit buttons QHBoxLayout *editButtonLayout = new QHBoxLayout; editButtonLayout->addStretch(); mRemove = new QPushButton(tr("&Remove")); connect(mRemove, SIGNAL(clicked()), this, SLOT(removeItem())); editButtonLayout->addWidget(mRemove); mAdd = new QPushButton(tr("&Add")); connect(mAdd, SIGNAL(clicked()), this, SLOT(addItem())); editButtonLayout->addWidget(mAdd); // main layout QVBoxLayout *mainLayout = new QVBoxLayout; mainLayout->addLayout(viewLayout); mainLayout->addLayout(editLayout); mainLayout->addLayout(editButtonLayout); setLayout(mainLayout); } void MappingEditorWidget::fillCompleter(const QStringList &completions){ mCompleterModel->setStringList(completions); } void MappingEditorWidget::setCurrentItems(const QStringList &items){ foreach(QString i, items){ QStandardItem *item = new QStandardItem(i); item->setIcon(mDecorationIcon); mModel->appendRow(item); } } QStringList MappingEditorWidget::items() const{ QStringList retval; for(int i = 0; i < mModel->rowCount(); ++i){ QStandardItem *item = mModel->item(i); retval << item->text(); } return retval; } void MappingEditorWidget::clear(){ mModel->clear(); mModel->setHorizontalHeaderItem(0, new QStandardItem(mCaption)); mEditor->clear(); } void MappingEditorWidget::addItem(){ QString itemName = mEditor->text(); if(itemName.isEmpty()){ return; } QList found = mModel->findItems(itemName, Qt::MatchFixedString); if(found.size()){ return; } QStandardItem *newItem = new QStandardItem(itemName); newItem->setIcon(mDecorationIcon); mModel->appendRow(newItem); mProxy->sort(0, mProxy->sortOrder()); mEditor->clear(); } void MappingEditorWidget::removeItem(){ QModelIndexList sel = mView->selectionModel()->selectedRows(); if(sel.isEmpty()){ return; } QModelIndex real = mProxy->mapToSource(sel.first()); mModel->removeRow(real.row()); } /* Mapping Editor */ MappingEditor::MappingEditor(const QString &caption, QWidget *parent, Qt::WindowFlags f) : QDialog(parent, f) { // Mapping Editor Widget mWidget = new MappingEditorWidget(caption); // buttons QHBoxLayout *buttonLayout = new QHBoxLayout; buttonLayout->addStretch(); mCancel = new QPushButton(tr("Cancel")); connect(mCancel, SIGNAL(clicked()), this, SLOT(reject())); buttonLayout->addWidget(mCancel); mAccept = new QPushButton(tr("Accept")); connect(mAccept, SIGNAL(clicked()), this, SLOT(accept())); buttonLayout->addWidget(mAccept); // dialog layout QVBoxLayout *mainLayout = new QVBoxLayout; mainLayout->addWidget(mWidget); mainLayout->addLayout(buttonLayout); setLayout(mainLayout); setMinimumWidth(300); } /* Metadata Editor Widget */ MetadataEditorWidget::MetadataEditorWidget(QWidget *parent) : QWidget(parent) { QLabel *captionL = new QLabel(tr("Edit Metadata")); QFormLayout *dataLayout = new QFormLayout; mReleaseYear = new QSpinBox; mReleaseYear->setMinimum(1900); mReleaseYear->setMaximum(3000); dataLayout->addRow(tr("&Release Year"), mReleaseYear); mSource = new QComboBox; mSource->setEditable(true); dataLayout->addRow(tr("&Source"), mSource); mRelGroup = new QComboBox; mRelGroup->setEditable(true); dataLayout->addRow(tr("Release &Group"), mRelGroup); mSubject = new QLineEdit; dataLayout->addRow(tr("Sub&ject"), mSubject); mEncoderOpts = new QLineEdit; dataLayout->addRow(tr("&Encoder Opts."), mEncoderOpts); mPasses = new QSpinBox; mPasses->setMinimum(0); mPasses->setMaximum(10); dataLayout->addRow(tr("&Passes"), mPasses); QVBoxLayout *commentLayout = new QVBoxLayout; QLabel *commentL = new QLabel(tr("Comment")); commentLayout->addWidget(commentL); mComment = new QTextEdit; commentLayout->addWidget(mComment); mWidgets << mReleaseYear << mSource << mRelGroup << mSubject << mEncoderOpts << mPasses << mComment; QVBoxLayout *mainLayout = new QVBoxLayout; mainLayout->addWidget(captionL); mainLayout->addLayout(dataLayout); mainLayout->addLayout(commentLayout); setLayout(mainLayout); } void MetadataEditorWidget::setSources(const QStringList &sources){ mSource->addItems(sources); } void MetadataEditorWidget::setReleaseGroups(const QStringList &relGroups){ mRelGroup->addItems(relGroups); } void MetadataEditorWidget::setMetadata(const QList &data){ mReleaseYear->setValue(data.at(ArchiveModel::ReleaseYear).toInt()); mSource->setCurrentText(data.at(ArchiveModel::Source).toString()); mSubject->setText(data.at(ArchiveModel::Subject).toString()); mRelGroup->setCurrentText(data.at(ArchiveModel::ReleaseGroup).toString()); mEncoderOpts->setText(data.at(ArchiveModel::EncoderOpts).toString()); mPasses->setValue(data.at(ArchiveModel::Passes).toInt()); mComment->setText(data.at(ArchiveModel::Comment).toString()); mAdded = data.at(ArchiveModel::Added).toDate(); } QList MetadataEditorWidget::metadata() const{ QList retval; for(int i = 0; i < ArchiveModel::MetadataNumFields; ++i){ retval << QVariant(); } retval[ArchiveModel::ReleaseYear] = mReleaseYear->value(); retval[ArchiveModel::Source] = mSource->currentText(); retval[ArchiveModel::Subject] = mSubject->text(); retval[ArchiveModel::ReleaseGroup] = mRelGroup->currentText(); retval[ArchiveModel::EncoderOpts] = mEncoderOpts->text(); retval[ArchiveModel::Passes] = mPasses->value(); retval[ArchiveModel::Comment] = mComment->toPlainText(); retval[ArchiveModel::Added] = mAdded; return retval; } void MetadataEditorWidget::setEnabledAll(bool enabled){ foreach(QWidget *w, mWidgets){ w->setEnabled(enabled); } } /* Metadata Editor */ MetadataEditor::MetadataEditor(QWidget *parent, Qt::WindowFlags f) : QDialog(parent, f){ mWidget = new MetadataEditorWidget; QHBoxLayout *buttonLayout = new QHBoxLayout; buttonLayout->addStretch(); mCancel = new QPushButton(tr("Cancel")); connect(mCancel, SIGNAL(clicked()), this, SLOT(reject())); buttonLayout->addWidget(mCancel); mAccept = new QPushButton(tr("Accept")); connect(mAccept, SIGNAL(clicked()), this, SLOT(accept())); buttonLayout->addWidget(mAccept); QVBoxLayout *mainLayout = new QVBoxLayout; mainLayout->addWidget(mWidget); mainLayout->addLayout(buttonLayout); setLayout(mainLayout); setMinimumWidth(400); } /* Part Editor */ PartEditor::PartEditor(QWidget *parent, Qt::WindowFlags f) : QDialog(parent, f){ QLabel *captionL = new QLabel(tr("Edit part")); QFormLayout *editLayout = new QFormLayout; // part no mPartNo = new QSpinBox; mPartNo->setMinimum(0); mPartNo->setMaximum(1024); editLayout->addRow(tr("Part &no"), mPartNo); // subtitle mSubtitle = new QLineEdit; editLayout->addRow(tr("&Subtitle"), mSubtitle); // buttons QHBoxLayout *buttonLayout = new QHBoxLayout; buttonLayout->addStretch(); mCancel = new QPushButton(tr("Cancel")); connect(mCancel, SIGNAL(clicked()), this, SLOT(reject())); mAccept = new QPushButton(tr("Accept")); connect(mAccept, SIGNAL(clicked()), this, SLOT(accept())); buttonLayout->addWidget(mCancel); buttonLayout->addWidget(mAccept); // main layout QVBoxLayout *mainLayout = new QVBoxLayout; mainLayout->addWidget(captionL); mainLayout->addLayout(editLayout); mainLayout->addLayout(buttonLayout); setLayout(mainLayout); } void PartEditor::setPartNo(int partNo){ mPartNo->setValue(partNo); } int PartEditor::partNo() const { return mPartNo->value(); } void PartEditor::setSubtitle(const QString &subtitle){ mSubtitle->setText(subtitle); } QString PartEditor::subtitle() const { return mSubtitle->text(); }