Commit 75d88783 authored by Waqar Ahmed's avatar Waqar Ahmed
Browse files

DocumentsTree: Allow rearranging items by DND

BUG: 267508
parent ea39a8fc
Pipeline #207375 passed with stage
in 7 minutes and 30 seconds
......@@ -92,16 +92,21 @@ private:
KateFileTree::KateFileTree(QWidget *parent)
: QTreeView(parent)
{
setAcceptDrops(false);
setIndentation(12);
setAllColumnsShowFocus(true);
setFocusPolicy(Qt::NoFocus);
setDragEnabled(true);
setDragDropMode(QAbstractItemView::DragOnly);
setSelectionBehavior(QAbstractItemView::SelectRows);
// for hover close button
viewport()->setAttribute(Qt::WA_Hover);
// DND
setDefaultDropAction(Qt::MoveAction);
setDragDropMode(QAbstractItemView::InternalMove);
setDragDropOverwriteMode(false);
setAcceptDrops(true);
setDropIndicatorShown(true);
setDragEnabled(true);
setItemDelegate(new StyleDelegate(this));
// handle activated (e.g. for pressing enter) + clicked (to avoid to need to do double-click e.g. on Windows)
......@@ -246,6 +251,13 @@ void KateFileTree::setupContextMenuActionGroups()
i18nc("@action:inmenu sorting option", "Opening Order"),
i18n("Sort by Opening Order"),
&KateFileTree::slotSortOpeningOrder);
m_customSorting = new QAction(QIcon(), i18n("Custom Sorting"), this);
m_customSorting->setCheckable(true);
m_customSorting->setActionGroup(sortGroup);
connect(m_customSorting, &QAction::triggered, this, [this] {
Q_EMIT sortRoleChanged(CustomSorting);
});
}
QAction *KateFileTree::setupOption(QActionGroup *group,
......@@ -337,6 +349,7 @@ void KateFileTree::contextMenuEvent(QContextMenuEvent *event)
m_sortByFile->setChecked(sortRole == Qt::DisplayRole);
m_sortByPath->setChecked(sortRole == KateFileTreeModel::PathRole);
m_sortByOpeningOrder->setChecked(sortRole == KateFileTreeModel::OpeningOrderRole);
m_customSorting->setChecked(sortRole == CustomSorting);
KTextEditor::Document *doc = docFromIndex(m_indexContextMenu);
const bool isFile = (nullptr != doc);
......@@ -392,6 +405,7 @@ void KateFileTree::contextMenuEvent(QContextMenuEvent *event)
sort_menu->addAction(m_sortByFile);
sort_menu->addAction(m_sortByPath);
sort_menu->addAction(m_sortByOpeningOrder);
sort_menu->addAction(m_customSorting);
menu.addAction(m_resetHistory);
......@@ -448,8 +462,6 @@ void KateFileTree::slotOpenWithMenuAction(QAction *a)
job->start();
}
Q_DECLARE_METATYPE(QList<KTextEditor::Document *>)
void KateFileTree::slotDocumentClose()
{
m_previouslySelected = QModelIndex();
......
......@@ -108,6 +108,7 @@ private:
QAction *m_sortByFile;
QAction *m_sortByPath;
QAction *m_sortByOpeningOrder;
QAction *m_customSorting;
QAction *m_resetHistory;
KateFileTreeProxyModel *m_proxyModel = nullptr;
......
......@@ -71,6 +71,7 @@ KateFileTreeConfigPage::KateFileTreeConfigPage(QWidget *parent, KateFileTreePlug
cmbSort->addItem(i18n("Opening Order"), static_cast<int>(KateFileTreeModel::OpeningOrderRole));
cmbSort->addItem(i18n("Document Name"), static_cast<int>(Qt::DisplayRole));
cmbSort->addItem(i18n("Url"), static_cast<int>(KateFileTreeModel::PathRole));
cmbSort->addItem(i18n("Custom Sorting"), static_cast<int>(CustomSorting));
// view mode
QHBoxLayout *lo3 = new QHBoxLayout;
......
......@@ -29,6 +29,24 @@
static constexpr int MaxHistoryItems = 10;
class FileTreeMimeData : public QMimeData
{
Q_OBJECT
public:
FileTreeMimeData(const QModelIndex &index)
: m_index(index)
{
}
QModelIndex index() const
{
return m_index;
}
private:
QPersistentModelIndex m_index;
};
class ProxyItemDir;
class ProxyItem
{
......@@ -485,7 +503,7 @@ Qt::ItemFlags KateFileTreeModel::flags(const QModelIndex &index) const
Qt::ItemFlags flags = Qt::ItemIsEnabled;
if (!index.isValid()) {
return Qt::NoItemFlags;
return Qt::NoItemFlags | Qt::ItemIsDropEnabled;
}
const ProxyItem *item = static_cast<ProxyItem *>(index.internalPointer());
......@@ -494,6 +512,10 @@ Qt::ItemFlags KateFileTreeModel::flags(const QModelIndex &index) const
flags |= Qt::ItemIsSelectable;
}
if (item->childCount() > 0) {
flags |= Qt::ItemIsDropEnabled;
}
if (item->doc() && item->doc()->url().isValid()) {
flags |= Qt::ItemIsDragEnabled;
}
......@@ -502,8 +524,6 @@ Qt::ItemFlags KateFileTreeModel::flags(const QModelIndex &index) const
return flags;
}
Q_DECLARE_METATYPE(QList<KTextEditor::Document *>)
QVariant KateFileTreeModel::data(const QModelIndex &index, int role) const
{
if (!index.isValid()) {
......@@ -572,28 +592,66 @@ QVariant KateFileTreeModel::data(const QModelIndex &index, int role) const
return QVariant();
}
QMimeData *KateFileTreeModel::mimeData(const QModelIndexList &indexes) const
Qt::DropActions KateFileTreeModel::supportedDropActions() const
{
QList<QUrl> urls;
for (const auto &index : indexes) {
ProxyItem *item = static_cast<ProxyItem *>(index.internalPointer());
if (!item || !item->doc() || !item->doc()->url().isValid()) {
continue;
}
Qt::DropActions a = QAbstractItemModel::supportedDropActions();
a |= Qt::MoveAction;
return a;
}
urls.append(item->doc()->url());
QMimeData *KateFileTreeModel::mimeData(const QModelIndexList &indexes) const
{
if (indexes.size() != columnCount()) {
return nullptr;
}
if (urls.isEmpty()) {
ProxyItem *item = static_cast<ProxyItem *>(indexes.at(0).internalPointer());
QList<QUrl> urls;
if (!item || !item->doc() || !item->doc()->url().isValid()) {
return nullptr;
}
urls.append(item->doc()->url());
QMimeData *mimeData = new QMimeData();
FileTreeMimeData *mimeData = new FileTreeMimeData(indexes.at(0));
mimeData->setUrls(urls);
return mimeData;
}
bool KateFileTreeModel::canDropMimeData(const QMimeData *data, Qt::DropAction action, int, int, const QModelIndex &parent) const
{
if (auto md = qobject_cast<const FileTreeMimeData *>(data)) {
return action == Qt::MoveAction && md->index().parent() == parent;
}
return false;
}
bool KateFileTreeModel::dropMimeData(const QMimeData *data, Qt::DropAction, int row, int, const QModelIndex &parent)
{
auto md = qobject_cast<const FileTreeMimeData *>(data);
if (!md) {
return false;
}
const auto index = md->index();
Q_ASSERT(parent == index.parent());
if (!index.isValid() || index.row() > rowCount(parent) || index.row() == row) {
return false;
}
auto parentItem = parent.isValid() ? static_cast<ProxyItemDir *>(parent.internalPointer()) : m_root;
auto &childs = parentItem->children();
int sourceRow = index.row();
beginMoveRows(index.parent(), index.row(), index.row(), parent, row);
childs.insert(row, childs.at(index.row()));
if (sourceRow > row) {
sourceRow++;
}
childs.takeAt(sourceRow);
endMoveRows();
return true;
}
QVariant KateFileTreeModel::headerData(int section, Qt::Orientation orientation, int role) const
{
Q_UNUSED(orientation);
......@@ -1328,3 +1386,5 @@ void KateFileTreeModel::resetHistory()
dataChanged(idx, idx, QVector<int>(1, Qt::BackgroundRole));
}
}
#include "katefiletreemodel.moc"
......@@ -48,6 +48,8 @@ public:
QMimeData *mimeData(const QModelIndexList &indexes) const override;
Qt::DropActions supportedDropActions() const override;
/* extra api for view */
QModelIndex docIndex(const KTextEditor::Document *) const;
......@@ -71,6 +73,9 @@ public:
void documentEdited(const KTextEditor::Document *);
void resetHistory();
bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) override;
bool canDropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) const override;
public Q_SLOTS:
void documentOpened(KTextEditor::Document *);
void documentClosed(KTextEditor::Document *);
......@@ -115,4 +120,6 @@ private:
bool m_listMode;
};
Q_DECLARE_METATYPE(QList<KTextEditor::Document *>)
#endif /* KATEFILETREEMODEL_H */
......@@ -195,11 +195,6 @@ KateFileTreePluginView::KateFileTreePluginView(KTextEditor::MainWindow *mainWind
});
m_fileTree->setModel(m_proxyModel);
m_fileTree->setDragEnabled(false);
m_fileTree->setDragDropMode(QAbstractItemView::InternalMove);
m_fileTree->setDropIndicatorShown(false);
m_fileTree->setSelectionMode(QAbstractItemView::SingleSelection);
connect(m_fileTree->selectionModel(), &QItemSelectionModel::currentChanged, m_fileTree, &KateFileTree::slotCurrentChanged);
......
......@@ -65,6 +65,7 @@ bool KateFileTreeProxyModel::lessThan(const QModelIndex &left, const QModelIndex
}
case KateFileTreeModel::OpeningOrderRole:
case CustomSorting:
return (left.row() - right.row()) < 0;
}
......
......@@ -14,6 +14,8 @@ namespace KTextEditor
class Document;
}
enum { CustomSorting = 1000 };
class KateFileTreeProxyModel : public QSortFilterProxyModel
{
Q_OBJECT
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment