mirror of
https://github.com/ciphervance/supercell-wx.git
synced 2025-10-30 13:30:06 +00:00
Drag and drop layers in the layer manager
This commit is contained in:
parent
14d6912014
commit
ec2663aee6
3 changed files with 153 additions and 4 deletions
|
|
@ -4,14 +4,16 @@
|
||||||
#include <scwx/qt/types/qt_types.hpp>
|
#include <scwx/qt/types/qt_types.hpp>
|
||||||
#include <scwx/util/logger.hpp>
|
#include <scwx/util/logger.hpp>
|
||||||
|
|
||||||
|
#include <set>
|
||||||
#include <variant>
|
#include <variant>
|
||||||
|
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
#include <QCheckBox>
|
#include <QCheckBox>
|
||||||
#include <QFontMetrics>
|
#include <QFontMetrics>
|
||||||
|
#include <QIODevice>
|
||||||
|
#include <QMimeData>
|
||||||
#include <QStyle>
|
#include <QStyle>
|
||||||
#include <QStyleOption>
|
#include <QStyleOption>
|
||||||
#include <boost/container/devector.hpp>
|
|
||||||
|
|
||||||
namespace scwx
|
namespace scwx
|
||||||
{
|
{
|
||||||
|
|
@ -30,6 +32,8 @@ static constexpr int kNumColumns = kLastColumn - kFirstColumn + 1;
|
||||||
|
|
||||||
static constexpr std::size_t kMapCount_ = 4u;
|
static constexpr std::size_t kMapCount_ = 4u;
|
||||||
|
|
||||||
|
static const QString kMimeFormat {"application/x.scwx-layer-model"};
|
||||||
|
|
||||||
typedef std::
|
typedef std::
|
||||||
variant<std::monostate, types::Layer, awips::Phenomenon, std::string>
|
variant<std::monostate, types::Layer, awips::Phenomenon, std::string>
|
||||||
LayerDescription;
|
LayerDescription;
|
||||||
|
|
@ -45,7 +49,7 @@ public:
|
||||||
std::array<bool, kMapCount_> displayed_ {true, true, true, true};
|
std::array<bool, kMapCount_> displayed_ {true, true, true, true};
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef boost::container::devector<LayerInfo> LayerVector;
|
typedef std::vector<LayerInfo> LayerVector;
|
||||||
|
|
||||||
explicit Impl(LayerModel* self) : self_ {self}
|
explicit Impl(LayerModel* self) : self_ {self}
|
||||||
{
|
{
|
||||||
|
|
@ -145,9 +149,21 @@ Qt::ItemFlags LayerModel::flags(const QModelIndex& index) const
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (layer.movable_)
|
||||||
|
{
|
||||||
|
flags |= Qt::ItemFlag::ItemIsDragEnabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
flags |= Qt::ItemFlag::ItemIsDropEnabled;
|
||||||
|
|
||||||
return flags;
|
return flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Qt::DropActions LayerModel::supportedDropActions() const
|
||||||
|
{
|
||||||
|
return Qt::DropAction::MoveAction;
|
||||||
|
}
|
||||||
|
|
||||||
QVariant LayerModel::data(const QModelIndex& index, int role) const
|
QVariant LayerModel::data(const QModelIndex& index, int role) const
|
||||||
{
|
{
|
||||||
static const QString enabledString = QObject::tr("Enabled");
|
static const QString enabledString = QObject::tr("Enabled");
|
||||||
|
|
@ -390,6 +406,117 @@ bool LayerModel::setData(const QModelIndex& index,
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QStringList LayerModel::mimeTypes() const
|
||||||
|
{
|
||||||
|
return {kMimeFormat};
|
||||||
|
}
|
||||||
|
|
||||||
|
QMimeData* LayerModel::mimeData(const QModelIndexList& indexes) const
|
||||||
|
{
|
||||||
|
// Get parent QMimeData
|
||||||
|
QMimeData* mimeData = QAbstractTableModel::mimeData(indexes);
|
||||||
|
|
||||||
|
// Generate LayerModel data
|
||||||
|
QByteArray data {};
|
||||||
|
QDataStream stream(&data, QIODevice::WriteOnly);
|
||||||
|
std::set<int> rows {};
|
||||||
|
|
||||||
|
for (auto& index : indexes)
|
||||||
|
{
|
||||||
|
if (!rows.contains(index.row()))
|
||||||
|
{
|
||||||
|
rows.insert(index.row());
|
||||||
|
stream << index.row();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set LayerModel data in QMimeData
|
||||||
|
mimeData->setData(kMimeFormat, data);
|
||||||
|
|
||||||
|
return mimeData;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool LayerModel::dropMimeData(const QMimeData* data,
|
||||||
|
Qt::DropAction /* action */,
|
||||||
|
int /* row */,
|
||||||
|
int /* column */,
|
||||||
|
const QModelIndex& parent)
|
||||||
|
{
|
||||||
|
QByteArray mimeData = data->data(kMimeFormat);
|
||||||
|
QDataStream stream(&mimeData, QIODevice::ReadOnly);
|
||||||
|
std::vector<int> sourceRows {};
|
||||||
|
|
||||||
|
// Read source rows from QMimeData
|
||||||
|
while (!stream.atEnd())
|
||||||
|
{
|
||||||
|
int sourceRow;
|
||||||
|
stream >> sourceRow;
|
||||||
|
sourceRows.push_back(sourceRow);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure rows are in numerical order
|
||||||
|
std::sort(sourceRows.begin(), sourceRows.end());
|
||||||
|
|
||||||
|
if (sourceRows.back() >= p->layers_.size())
|
||||||
|
{
|
||||||
|
logger_->error("Cannot perform drop action, invalid source rows");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Nothing to insert
|
||||||
|
if (sourceRows.empty())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a copy of the layers to insert (don't insert in-place)
|
||||||
|
std::vector<Impl::LayerInfo> newLayers {};
|
||||||
|
for (auto& sourceRow : sourceRows)
|
||||||
|
{
|
||||||
|
newLayers.push_back(p->layers_.at(sourceRow));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Insert the copied layers
|
||||||
|
auto insertPosition = p->layers_.begin() + parent.row();
|
||||||
|
beginInsertRows(QModelIndex(),
|
||||||
|
parent.row(),
|
||||||
|
parent.row() + static_cast<int>(sourceRows.size()) - 1);
|
||||||
|
p->layers_.insert(insertPosition, newLayers.begin(), newLayers.end());
|
||||||
|
endInsertRows();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool LayerModel::removeRows(int row, int count, const QModelIndex& parent)
|
||||||
|
{
|
||||||
|
// Validate count
|
||||||
|
if (count <= 0)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove rows
|
||||||
|
auto erasePosition = p->layers_.begin() + row;
|
||||||
|
for (int i = 0; i < count; ++i)
|
||||||
|
{
|
||||||
|
if (erasePosition->movable_)
|
||||||
|
{
|
||||||
|
// Remove the current row if movable
|
||||||
|
beginRemoveRows(parent, row, row);
|
||||||
|
erasePosition = p->layers_.erase(erasePosition);
|
||||||
|
endRemoveRows();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Don't remove immovable rows
|
||||||
|
++erasePosition;
|
||||||
|
++row;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void LayerModel::HandlePlacefileRemoved(const std::string& name)
|
void LayerModel::HandlePlacefileRemoved(const std::string& name)
|
||||||
{
|
{
|
||||||
auto it =
|
auto it =
|
||||||
|
|
@ -489,7 +616,7 @@ void LayerModel::Impl::AddPlacefile(const std::string& name)
|
||||||
|
|
||||||
// Placefile is new, add row
|
// Placefile is new, add row
|
||||||
self_->beginInsertRows(QModelIndex(), 0, 0);
|
self_->beginInsertRows(QModelIndex(), 0, 0);
|
||||||
layers_.insert(insertPosition, {types::LayerType::Placefile, name});
|
layers_.insert(insertPosition, {types::LayerType::Placefile, name, true});
|
||||||
self_->endInsertRows();
|
self_->endInsertRows();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -40,7 +40,8 @@ public:
|
||||||
int rowCount(const QModelIndex& parent = QModelIndex()) const override;
|
int rowCount(const QModelIndex& parent = QModelIndex()) const override;
|
||||||
int columnCount(const QModelIndex& parent = QModelIndex()) const override;
|
int columnCount(const QModelIndex& parent = QModelIndex()) const override;
|
||||||
|
|
||||||
Qt::ItemFlags flags(const QModelIndex& index) const override;
|
Qt::ItemFlags flags(const QModelIndex& index) const override;
|
||||||
|
Qt::DropActions supportedDropActions() const override;
|
||||||
|
|
||||||
QVariant data(const QModelIndex& index,
|
QVariant data(const QModelIndex& index,
|
||||||
int role = Qt::DisplayRole) const override;
|
int role = Qt::DisplayRole) const override;
|
||||||
|
|
@ -52,6 +53,18 @@ public:
|
||||||
const QVariant& value,
|
const QVariant& value,
|
||||||
int role = Qt::EditRole) override;
|
int role = Qt::EditRole) override;
|
||||||
|
|
||||||
|
QStringList mimeTypes() const override;
|
||||||
|
QMimeData* mimeData(const QModelIndexList& indexes) const override;
|
||||||
|
|
||||||
|
bool dropMimeData(const QMimeData* data,
|
||||||
|
Qt::DropAction action,
|
||||||
|
int row,
|
||||||
|
int column,
|
||||||
|
const QModelIndex& parent) override;
|
||||||
|
bool removeRows(int row,
|
||||||
|
int count,
|
||||||
|
const QModelIndex& parent = QModelIndex()) override;
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void HandlePlacefileRemoved(const std::string& name);
|
void HandlePlacefileRemoved(const std::string& name);
|
||||||
void HandlePlacefileRenamed(const std::string& oldName,
|
void HandlePlacefileRenamed(const std::string& oldName,
|
||||||
|
|
|
||||||
|
|
@ -37,6 +37,15 @@
|
||||||
</property>
|
</property>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QTreeView" name="layerTreeView">
|
<widget class="QTreeView" name="layerTreeView">
|
||||||
|
<property name="dragEnabled">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="dragDropMode">
|
||||||
|
<enum>QAbstractItemView::InternalMove</enum>
|
||||||
|
</property>
|
||||||
|
<property name="defaultDropAction">
|
||||||
|
<enum>Qt::MoveAction</enum>
|
||||||
|
</property>
|
||||||
<property name="alternatingRowColors">
|
<property name="alternatingRowColors">
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
</property>
|
</property>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue