Russian Qt Forum
Ноябрь 25, 2024, 01:45 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1] 2   Вниз
  Печать  
Автор Тема: Drag drop папки или нескольких папок  (Прочитано 8191 раз)
koldun90
Крякер
****
Offline Offline

Сообщений: 345


Просмотр профиля
« : Июнь 24, 2014, 08:53 »

Добрый день форумчане есть проблема в реализации драг дропа папок (драг дроп осуществляется treeview И treeview_2
в которых представлена файловая система)

Собственно treeview

Код:
model1->setRootPath(QDir::currentPath());
    model1->setFilter(QDir::AllDirs | QDir::Files |QDir::NoDot);
    model1->setReadOnly(false);    /
    ui->treeview->setModel(model1);

Собственно treeview_2

Код:
model2->setRootPath(QDir::currentPath());
    model2->setFilter(QDir::AllDirs | QDir::Files |QDir::NoDot);
    model2->setReadOnly(false);
    ui->treeview_2->setModel(model2);

Разрешаю виджетам принимать дропы

Код:
ui->treeView->setAcceptDrops(true);  
ui->treeView_2->setAcceptDrops(true);

В общем treeview и treeView_2 наследуются от mytreeview
Здесь все норм у меня

Далее идет класс mytreeview

Код:
#include <mainwindow.h>
#include "mytreeview.h"
#include <QApplication>
extern int flag;
mytreeview::mytreeview(QWidget *parent)
    :QTreeView(parent)
{
}
void mytreeview::mousePressEvent(QMouseEvent *event)    //событие при нажатии мышки
{
    if (event->button() == Qt::RightButton) //в случае нажатия правой кнопки мыши
    {
       emit sg();  //испускаем сигнал который активирует контекнсное меню
    }
    if (event->button()==Qt::LeftButton)     //если зажата левая кнопка мыши
    {
        m_ptDragPos=event->pos();   //определяем позицию указателя (первоначальная позиция указателя)
        emit activation();   //испускаем сигнал который активирует метод определения активации окна
    }
        QTreeView::mousePressEvent(event);   //передаем событию qtreeview
}
void mytreeview::keyPressEvent(QKeyEvent *event)   // событие при нажатии клавиши
{
    if (event->key()==Qt::Key_Control)   //если нажата кнопка контрол
    {
        emit sg2(1,1);   //посылаем сигнал на мультиселекцию
    }
    if (event->key()==Qt::Key_C && event->modifiers()==Qt::ControlModifier)      //при нажатии клавиш ctrl+c
    {
        emit ctrl_c();     //вызываем сигнал   который активирует копирование
    }
    if (event->key()==Qt::Key_Delete)   //в случае нажатия клавиши делет
    {
        emit key_delete();    //запускаем удаления объекта
    }
    if (event->key()==Qt::Key_V && event->modifiers()==Qt::ControlModifier)   //в случае нажатия сочетания клавиш кнтрл+в
    {
        emit ctrl_v();   //запускаем вставку
    }
    if (event->key()==Qt::Key_X && event->modifiers()==Qt::ControlModifier)   // в лучае нажатия клавиш кнтрл+х
    {
        emit ctrl_x();  //активирует сигнал который включает вырезание файла
    }
    if (event->key()==Qt::Key_F2)     //в случае нажатия клавиши F2
    {
        emit F2();
    }
        QTreeView::keyPressEvent(event);
}
void mytreeview::keyReleaseEvent(QKeyEvent *event)    // событие при отпускании клавиши
{
    if (event->key()==Qt::Key_Control)
    {
        emit sg2(2,0); //посылаем сигнал на одиночную селекцию
    }
    if (event->key()==Qt::Key_C && event->modifiers()==Qt::ControlModifier)
    {
        emit sg2(2,0); //посылаем сигнал на одиночную селекцию
    }
    if (event->key()==Qt::Key_V && event->modifiers()==Qt::ControlModifier)
    {
        emit sg2(2,0); //посылаем сигнал на одиночную селекцию
    }
    else
    {
        QTreeView::keyReleaseEvent(event);
    }
}
void mytreeview::startDrag()   //старт метода переноса данных
{
    pMimeData=new QMimeData; //создаем новый объект класса QMimeData
    pMimeData->setText("text/uri-list");   //вводим текст
    pDrag=new QDrag(this);     // создаем новый объект класса QDrag
    pDrag->setMimeData(pMimeData);
    pDrag->exec(Qt::CopyAction);
}
void mytreeview::mouseMoveEvent(QMouseEvent *event)  //событие при зажатой ЛКМ при перетаскивании в сторону
{
    if (event->buttons() && Qt::LeftButton) //если зажата левая кнопка мыши
    {
        int distance=(event->pos()-m_ptDragPos).manhattanLength();    //вычисляем расстояние текущей позиции указателя-первоначальной позиции указателя в которой была нажата ЛКМ
        if (distance> QApplication::startDragDistance())  //если расстояние больше чем возвращаемое расстояние статистического метода
        //startdragdistance(которое равно по умолчанию 4 пикселя) значит активируется операция перетаскивания
            //если меньше пользователя случайно двинул указаетль мыши
        {
            startDrag();
        }
    }
    QTreeView::mouseMoveEvent(event);
}
void mytreeview::dragEnterEvent(QDragEnterEvent *event)   //метод вызывается каждый раз когда объект пересекает границу виджета
{
    if (event->mimeData()->hasFormat("text/plain"))     // если перетаскиваемы объект файл
    {
        event->acceptProposedAction();  // сообщение виджета о готовности принять объект
    }
    QTreeView::dragEnterEvent(event);
}
void mytreeview::dropEvent(QDropEvent *event)
{
    QList<QUrl> urlList=event->mimeData()->urls();
    QString str;
    foreach (QUrl url,urlList)
    {
        str=str+url.toString()+"\n";
        MainWindow fv;
        fv.otobr(str);       
    }
    QTreeView::dropEvent(event);
}

Программа работает,но она как бы переносит только один файл или несколько.
Работает она так:
1)Вы зажали ЛКМ
2)затем начинаете отводить (когда вы отводите драг дроп по прежнему недоступен)
3) Драг дроп активируется только тогда когда вы ОТПУСКАЕТЕ ЛКМ( появляется значок+ в Linux)
А должно быть так соответственно чтобы когда я отвел выделенный элемент на достаточное расстояние активировалось перетаскивание( БЕЗ ОТПУСКАНИЯ ЛКМ)
А у меня почему то активируется только при отпускании ЛКМ.

Соответственно у меня вопросы:
1)Как решить вопрос чтоб драг дроп активировался без отпускания ЛКМ
2) Что нужно сделать (или что переопределить) чтобы программа драг дропала папку или несколько папок?
Записан
carrygun
Гость
« Ответ #1 : Июнь 24, 2014, 10:26 »

1) В startDrag() написать pDrag->exec(Qt::CopyAction | Qt::MoveAction, Qt::CopyAction);
2) Писать свою логику, например пихать список папок/файлов в mimeData для QDrag объекта.
Записан
koldun90
Крякер
****
Offline Offline

Сообщений: 345


Просмотр профиля
« Ответ #2 : Июнь 24, 2014, 11:49 »

1) В startDrag() написать pDrag->exec(Qt::CopyAction | Qt::MoveAction, Qt::CopyAction);
2) Писать свою логику, например пихать список папок/файлов в mimeData для QDrag объекта.

Вы не могли бы подробнее объяснить по второму пункту если можно....

по первому пункту ничего не изменилось
драг дроп активируется только после отпускания ЛКМ вне зависимости от расстояния
« Последнее редактирование: Июнь 24, 2014, 11:54 от koldun90 » Записан
kambala
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4747



Просмотр профиля WWW
« Ответ #3 : Июнь 24, 2014, 12:20 »

2) юрлы там из воздуха не появятся, их надо добавить при создании объекта мимедата. а сейчас ты передаешь одну текстовую строку в мимедата.

Код:
        MainWindow fv;
        fv.otobr(str);   
эту чушь убери вообще. если тебе надо передать строки главному окну, испусти сигнал.

по возможности выложи компилируемый пример.
Записан

Изучением C++ вымощена дорога в Qt.

UTF-8 has been around since 1993 and Unicode 2.0 since 1996; if you have created any 8-bit character content since 1996 in anything other than UTF-8, then I hate you. © Matt Gallagher
koldun90
Крякер
****
Offline Offline

Сообщений: 345


Просмотр профиля
« Ответ #4 : Июнь 24, 2014, 13:22 »

2) юрлы там из воздуха не появятся, их надо добавить при создании объекта мимедата. а сейчас ты передаешь одну текстовую строку в мимедата.

чтобы реализовать драг дроп папок я так понял нужно:
Код:
pMimeData->setText();
    // в аргументе setText должен быть список всех файлов и папок которые я выбрал для драга да?
Код:
pMimeData=new QMimeData()
  или здесь их нужно добавить? И юрлы -это полные пути папок и файлов которые я выбрал для драга?

Записан
kambala
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4747



Просмотр профиля WWW
« Ответ #5 : Июнь 24, 2014, 14:25 »

документацию что ли не можешь открыть?
void QMimeData::setUrls(const QList<QUrl> & urls)
И юрлы -это полные пути папок и файлов которые я выбрал для драга?
да
Записан

Изучением C++ вымощена дорога в Qt.

UTF-8 has been around since 1993 and Unicode 2.0 since 1996; if you have created any 8-bit character content since 1996 in anything other than UTF-8, then I hate you. © Matt Gallagher
koldun90
Крякер
****
Offline Offline

Сообщений: 345


Просмотр профиля
« Ответ #6 : Июнь 24, 2014, 14:51 »

документацию что ли не можешь открыть?
void QMimeData::setUrls(const QList<QUrl> & urls)
И юрлы -это полные пути папок и файлов которые я выбрал для драга?
да
Теперь не понятно откуда мне взять список QList<QUrl>?
каким методом?
потому что у меня есть список только QStringlist
Записан
Zerkin
Чайник
*
Offline Offline

Сообщений: 98


Просмотр профиля
« Ответ #7 : Июнь 24, 2014, 15:08 »

Твой QStringList это по большому счету QList<QString>.  

Конструктор QUrl

Код
C++ (Qt)
QUrl(const QString & url )

Дальше, думаю, понятно.

Код
C++ (Qt)
QList<QUrl> fromStringList(const QStringList &urls, ParsingMode mode)
{
   QList<QUrl> lst;
   lst.reserve(urls.size());
   foreach (const QString &str, urls) {
       lst.append(QUrl(str, mode));
   }
   return lst;
}

https://qt.gitorious.org/qt/odysseus-qtbase/commit/6b9545a
« Последнее редактирование: Июнь 24, 2014, 15:14 от Zerkin » Записан
koldun90
Крякер
****
Offline Offline

Сообщений: 345


Просмотр профиля
« Ответ #8 : Июнь 24, 2014, 15:34 »

Твой QStringList это по большому счету QList<QString>.  

Конструктор QUrl

Код
C++ (Qt)
QUrl(const QString & url )

Дальше, думаю, понятно.

Код
C++ (Qt)
QList<QUrl> fromStringList(const QStringList &urls, ParsingMode mode)
{
   QList<QUrl> lst;
   lst.reserve(urls.size());
   foreach (const QString &str, urls) {
       lst.append(QUrl(str, mode));
   }
   return lst;
}

https://qt.gitorious.org/qt/odysseus-qtbase/commit/6b9545a

я так понял вы написали функцию которая превращает список QStringList в QList<QUrl>
Записан
Zerkin
Чайник
*
Offline Offline

Сообщений: 98


Просмотр профиля
« Ответ #9 : Июнь 24, 2014, 15:43 »

Правильно поняли  Улыбающийся
Записан
koldun90
Крякер
****
Offline Offline

Сообщений: 345


Просмотр профиля
« Ответ #10 : Июнь 25, 2014, 08:32 »

Правильно поняли  Улыбающийся

ParsingMode mode--это что за параметр функции?

и еще вопрос по поводу QMimeData::setUrls(const QList<QUrl> & urls)
 если в списке окажется папка он ее дропнет как бы? или нужно для папки что то еще делать?

Записан
gil9red
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 1805



Просмотр профиля WWW
« Ответ #11 : Июнь 25, 2014, 08:47 »

ParsingMode mode--это что за параметр функции?

QUrl::ParsingMode
Записан

kambala
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4747



Просмотр профиля WWW
« Ответ #12 : Июнь 25, 2014, 10:19 »

и еще вопрос по поводу QMimeData::setUrls(const QList<QUrl> & urls)
 если в списке окажется папка он ее дропнет как бы? или нужно для папки что то еще делать?
в view::dropEvent / model::dropMimeData опиши необходимую логику
Записан

Изучением C++ вымощена дорога в Qt.

UTF-8 has been around since 1993 and Unicode 2.0 since 1996; if you have created any 8-bit character content since 1996 in anything other than UTF-8, then I hate you. © Matt Gallagher
koldun90
Крякер
****
Offline Offline

Сообщений: 345


Просмотр профиля
« Ответ #13 : Июнь 25, 2014, 12:17 »

и еще вопрос по поводу QMimeData::setUrls(const QList<QUrl> & urls)
 если в списке окажется папка он ее дропнет как бы? или нужно для папки что то еще делать?
в view::dropEvent / model::dropMimeData опиши необходимую логику

view::dropEvent --это я так понял здесь нужно писать void mytreeview::dropEvent(QDropEvent *event)?
я так понял  когда будет происходить дроп
нужно смотреть что дропается?
если дропается файл то ничего не делать...(он как бы и по умлочанию дропается
а если дропается папка то нужно как бы скопировать эту папку в приемник(вместе со всеми поддиректориями и файлами).
Только получается как мне узнать путь куда я дропую программно.
Выделил файл, начал отодвигать, активировался дроп , навел на папку в другом окне( куда я собираюсь дропать ...)

ps: Получается дроп папки сводится грубо говоря к копированию этой папки(вместе с ее поддиректориями и файлами) из источника в приемник?
Записан
kambala
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4747



Просмотр профиля WWW
« Ответ #14 : Июнь 25, 2014, 20:56 »

bool QAbstractItemModel::dropMimeData(const QMimeData * data, Qt::DropAction action, int row, int column, const QModelIndex & parent) [virtual] — выделенная часть позволит узнать куда совершается дроп
ps: Получается дроп папки сводится грубо говоря к копированию этой папки(вместе с ее поддиректориями и файлами) из источника в приемник?
естественно Улыбающийся
Записан

Изучением C++ вымощена дорога в Qt.

UTF-8 has been around since 1993 and Unicode 2.0 since 1996; if you have created any 8-bit character content since 1996 in anything other than UTF-8, then I hate you. © Matt Gallagher
Страниц: [1] 2   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.125 секунд. Запросов: 23.