Hide use of boost multi-index behind pimpl.

This commit is contained in:
John Maguire 2014-02-06 17:44:29 +01:00
parent 71893e4847
commit 8d1f4612db
4 changed files with 139 additions and 116 deletions

View File

@ -22,14 +22,61 @@
#include <limits>
// boost::multi_index still relies on these being in the global namespace.
using std::placeholders::_1;
using std::placeholders::_2;
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/member.hpp>
#include <boost/multi_index/hashed_index.hpp>
#include <boost/multi_index/ordered_index.hpp>
using boost::multi_index::hashed_unique;
using boost::multi_index::identity;
using boost::multi_index::indexed_by;
using boost::multi_index::member;
using boost::multi_index::multi_index_container;
using boost::multi_index::ordered_unique;
using boost::multi_index::tag;
std::size_t hash_value(const QModelIndex& index) {
return qHash(index);
}
namespace {
struct Mapping {
Mapping(const QModelIndex& _source_index)
: source_index(_source_index) {}
QModelIndex source_index;
};
struct tag_by_source {};
struct tag_by_pointer {};
} // namespace
class MergedProxyModelPrivate {
private:
typedef multi_index_container<
Mapping*,
indexed_by<
hashed_unique<tag<tag_by_source>,
member<Mapping, QModelIndex, &Mapping::source_index> >,
ordered_unique<tag<tag_by_pointer>,
identity<Mapping*> >
>
> MappingContainer;
public:
MappingContainer mappings_;
};
MergedProxyModel::MergedProxyModel(QObject* parent)
: QAbstractProxyModel(parent),
resetting_model_(nullptr)
{
resetting_model_(nullptr),
p_(new MergedProxyModelPrivate) {
}
MergedProxyModel::~MergedProxyModel() {
@ -37,10 +84,8 @@ MergedProxyModel::~MergedProxyModel() {
}
void MergedProxyModel::DeleteAllMappings() {
MappingContainer::index<tag_by_pointer>::type::iterator begin =
mappings_.get<tag_by_pointer>().begin();
MappingContainer::index<tag_by_pointer>::type::iterator end =
mappings_.get<tag_by_pointer>().end();
const auto& begin = p_->mappings_.get<tag_by_pointer>().begin();
const auto& end = p_->mappings_.get<tag_by_pointer>().end();
qDeleteAll(begin, end);
}
@ -88,14 +133,12 @@ void MergedProxyModel::RemoveSubModel(const QModelIndex &source_parent) {
resetting_model_ = nullptr;
// Delete all the mappings that reference the submodel
MappingContainer::index<tag_by_pointer>::type::iterator it =
mappings_.get<tag_by_pointer>().begin();
MappingContainer::index<tag_by_pointer>::type::iterator end =
mappings_.get<tag_by_pointer>().end();
auto it = p_->mappings_.get<tag_by_pointer>().begin();
auto end = p_->mappings_.get<tag_by_pointer>().end();
while (it != end) {
if ((*it)->source_index.model() == submodel) {
delete *it;
it = mappings_.get<tag_by_pointer>().erase(it);
it = p_->mappings_.get<tag_by_pointer>().erase(it);
} else {
++it;
}
@ -145,7 +188,7 @@ void MergedProxyModel::SourceModelReset() {
DeleteAllMappings();
// Clear the containers
mappings_.clear();
p_->mappings_.clear();
merge_points_.clear();
// Reset the proxy
@ -170,14 +213,12 @@ void MergedProxyModel::SubModelReset() {
resetting_model_ = nullptr;
// Delete all the mappings that reference the submodel
MappingContainer::index<tag_by_pointer>::type::iterator it =
mappings_.get<tag_by_pointer>().begin();
MappingContainer::index<tag_by_pointer>::type::iterator end =
mappings_.get<tag_by_pointer>().end();
auto it = p_->mappings_.get<tag_by_pointer>().begin();
auto end = p_->mappings_.get<tag_by_pointer>().end();
while (it != end) {
if ((*it)->source_index.model() == submodel) {
delete *it;
it = mappings_.get<tag_by_pointer>().erase(it);
it = p_->mappings_.get<tag_by_pointer>().erase(it);
} else {
++it;
}
@ -227,8 +268,8 @@ QModelIndex MergedProxyModel::mapToSource(const QModelIndex& proxy_index) const
return QModelIndex();
Mapping* mapping = static_cast<Mapping*>(proxy_index.internalPointer());
if (mappings_.get<tag_by_pointer>().find(mapping) ==
mappings_.get<tag_by_pointer>().end())
if (p_->mappings_.get<tag_by_pointer>().find(mapping) ==
p_->mappings_.get<tag_by_pointer>().end())
return QModelIndex();
if (mapping->source_index.model() == resetting_model_)
return QModelIndex();
@ -243,14 +284,14 @@ QModelIndex MergedProxyModel::mapFromSource(const QModelIndex& source_index) con
return QModelIndex();
// Add a mapping if we don't have one already
MappingContainer::index<tag_by_source>::type::iterator it =
mappings_.get<tag_by_source>().find(source_index);
const auto& it =
p_->mappings_.get<tag_by_source>().find(source_index);
Mapping* mapping;
if (it != mappings_.get<tag_by_source>().end()) {
if (it != p_->mappings_.get<tag_by_source>().end()) {
mapping = *it;
} else {
mapping = new Mapping(source_index);
const_cast<MergedProxyModel*>(this)->mappings_.insert(mapping);
const_cast<MergedProxyModel*>(this)->p_->mappings_.insert(mapping);
}
return createIndex(source_index.row(), source_index.column(), mapping);

View File

@ -18,26 +18,14 @@
#ifndef MERGEDPROXYMODEL_H
#define MERGEDPROXYMODEL_H
#include <memory>
#include <QAbstractProxyModel>
using std::placeholders::_1;
using std::placeholders::_2;
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/member.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <boost/multi_index/hashed_index.hpp>
using boost::multi_index::multi_index_container;
using boost::multi_index::indexed_by;
using boost::multi_index::hashed_unique;
using boost::multi_index::ordered_unique;
using boost::multi_index::tag;
using boost::multi_index::member;
using boost::multi_index::identity;
std::size_t hash_value(const QModelIndex& index);
class MergedProxyModelPrivate;
class MergedProxyModel : public QAbstractProxyModel {
Q_OBJECT
@ -105,30 +93,13 @@ class MergedProxyModel : public QAbstractProxyModel {
void DeleteAllMappings();
bool IsKnownModel(const QAbstractItemModel* model) const;
struct Mapping {
Mapping(const QModelIndex& _source_index)
: source_index(_source_index) {}
QModelIndex source_index;
};
struct tag_by_source {};
struct tag_by_pointer {};
typedef multi_index_container<
Mapping*,
indexed_by<
hashed_unique<tag<tag_by_source>,
member<Mapping, QModelIndex, &Mapping::source_index> >,
ordered_unique<tag<tag_by_pointer>,
identity<Mapping*> >
>
> MappingContainer;
MappingContainer mappings_;
QMap<QAbstractItemModel*, QPersistentModelIndex> merge_points_;
QAbstractItemModel* resetting_model_;
QMap<QAbstractItemModel*, QModelIndex> old_merge_points_;
std::unique_ptr<MergedProxyModelPrivate> p_;
};
#endif // MERGEDPROXYMODEL_H

View File

@ -20,25 +20,69 @@
#include <QPushButton>
// boost::multi_index still relies on these being in the global namespace.
using std::placeholders::_1;
using std::placeholders::_2;
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/member.hpp>
#include <boost/multi_index/ordered_index.hpp>
using boost::multi_index_container;
using boost::multi_index::indexed_by;
using boost::multi_index::ordered_unique;
using boost::multi_index::tag;
using boost::multi_index::member;
namespace {
struct Mapping {
Mapping(LibraryModel::GroupBy g, int i) : group_by(g), combo_box_index(i) {}
LibraryModel::GroupBy group_by;
int combo_box_index;
};
struct tag_index {};
struct tag_group_by {};
} // namespace
class GroupByDialogPrivate {
private:
typedef multi_index_container<
Mapping,
indexed_by<
ordered_unique<tag<tag_index>,
member<Mapping, int, &Mapping::combo_box_index> >,
ordered_unique<tag<tag_group_by>,
member<Mapping, LibraryModel::GroupBy, &Mapping::group_by> >
>
> MappingContainer;
public:
MappingContainer mapping_;
};
GroupByDialog::GroupByDialog(QWidget *parent)
: QDialog(parent),
ui_(new Ui_GroupByDialog)
{
ui_(new Ui_GroupByDialog),
p_(new GroupByDialogPrivate) {
ui_->setupUi(this);
Reset();
mapping_.insert(Mapping(LibraryModel::GroupBy_None, 0));
mapping_.insert(Mapping(LibraryModel::GroupBy_Album, 1));
mapping_.insert(Mapping(LibraryModel::GroupBy_Artist, 2));
mapping_.insert(Mapping(LibraryModel::GroupBy_AlbumArtist, 3));
mapping_.insert(Mapping(LibraryModel::GroupBy_Composer, 4));
mapping_.insert(Mapping(LibraryModel::GroupBy_FileType, 5));
mapping_.insert(Mapping(LibraryModel::GroupBy_Genre, 6));
mapping_.insert(Mapping(LibraryModel::GroupBy_Year, 7));
mapping_.insert(Mapping(LibraryModel::GroupBy_YearAlbum, 8));
mapping_.insert(Mapping(LibraryModel::GroupBy_Bitrate, 9));
mapping_.insert(Mapping(LibraryModel::GroupBy_Performer, 10));
mapping_.insert(Mapping(LibraryModel::GroupBy_Grouping, 11));
p_->mapping_.insert(Mapping(LibraryModel::GroupBy_None, 0));
p_->mapping_.insert(Mapping(LibraryModel::GroupBy_Album, 1));
p_->mapping_.insert(Mapping(LibraryModel::GroupBy_Artist, 2));
p_->mapping_.insert(Mapping(LibraryModel::GroupBy_AlbumArtist, 3));
p_->mapping_.insert(Mapping(LibraryModel::GroupBy_Composer, 4));
p_->mapping_.insert(Mapping(LibraryModel::GroupBy_FileType, 5));
p_->mapping_.insert(Mapping(LibraryModel::GroupBy_Genre, 6));
p_->mapping_.insert(Mapping(LibraryModel::GroupBy_Year, 7));
p_->mapping_.insert(Mapping(LibraryModel::GroupBy_YearAlbum, 8));
p_->mapping_.insert(Mapping(LibraryModel::GroupBy_Bitrate, 9));
p_->mapping_.insert(Mapping(LibraryModel::GroupBy_Performer, 10));
p_->mapping_.insert(Mapping(LibraryModel::GroupBy_Grouping, 11));
connect(ui_->button_box->button(QDialogButtonBox::Reset), SIGNAL(clicked()),
SLOT(Reset()));
@ -46,9 +90,7 @@ GroupByDialog::GroupByDialog(QWidget *parent)
resize(sizeHint());
}
GroupByDialog::~GroupByDialog() {
delete ui_;
}
GroupByDialog::~GroupByDialog() {}
void GroupByDialog::Reset() {
ui_->first->setCurrentIndex(2); // Artist
@ -58,14 +100,14 @@ void GroupByDialog::Reset() {
void GroupByDialog::accept() {
emit Accepted(LibraryModel::Grouping(
mapping_.get<tag_index>().find(ui_->first->currentIndex())->group_by,
mapping_.get<tag_index>().find(ui_->second->currentIndex())->group_by,
mapping_.get<tag_index>().find(ui_->third->currentIndex())->group_by));
p_->mapping_.get<tag_index>().find(ui_->first->currentIndex())->group_by,
p_->mapping_.get<tag_index>().find(ui_->second->currentIndex())->group_by,
p_->mapping_.get<tag_index>().find(ui_->third->currentIndex())->group_by));
QDialog::accept();
}
void GroupByDialog::LibraryGroupingChanged(const LibraryModel::Grouping& g) {
ui_->first->setCurrentIndex(mapping_.get<tag_group_by>().find(g[0])->combo_box_index);
ui_->second->setCurrentIndex(mapping_.get<tag_group_by>().find(g[1])->combo_box_index);
ui_->third->setCurrentIndex(mapping_.get<tag_group_by>().find(g[2])->combo_box_index);
ui_->first->setCurrentIndex(p_->mapping_.get<tag_group_by>().find(g[0])->combo_box_index);
ui_->second->setCurrentIndex(p_->mapping_.get<tag_group_by>().find(g[1])->combo_box_index);
ui_->third->setCurrentIndex(p_->mapping_.get<tag_group_by>().find(g[2])->combo_box_index);
}

View File

@ -22,28 +22,16 @@
#include <memory>
using std::placeholders::_1;
using std::placeholders::_2;
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/member.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include "librarymodel.h"
class GroupByDialogPrivate;
class Ui_GroupByDialog;
using boost::multi_index_container;
using boost::multi_index::indexed_by;
using boost::multi_index::ordered_unique;
using boost::multi_index::tag;
using boost::multi_index::member;
class GroupByDialog : public QDialog {
Q_OBJECT
public:
GroupByDialog(QWidget *parent = 0);
GroupByDialog(QWidget* parent = nullptr);
~GroupByDialog();
public slots:
@ -57,27 +45,8 @@ class GroupByDialog : public QDialog {
void Reset();
private:
struct Mapping {
Mapping(LibraryModel::GroupBy g, int i) : group_by(g), combo_box_index(i) {}
LibraryModel::GroupBy group_by;
int combo_box_index;
};
struct tag_index {};
struct tag_group_by {};
typedef multi_index_container<
Mapping,
indexed_by<
ordered_unique<tag<tag_index>,
member<Mapping, int, &Mapping::combo_box_index> >,
ordered_unique<tag<tag_group_by>,
member<Mapping, LibraryModel::GroupBy, &Mapping::group_by> >
>
> MappingContainer;
MappingContainer mapping_;
Ui_GroupByDialog* ui_;
std::unique_ptr<Ui_GroupByDialog> ui_;
std::unique_ptr<GroupByDialogPrivate> p_;
};
#endif // GROUPBYDIALOG_H