SlideShare a Scribd company logo
Ch9.Drag and Drop
        Browny
      23, May, 2011
Outline


• Enabling Drag and Drop
• Supporting Custom Drag Types
• Clipboard Handling
Drag file onto Window (1/4)
class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow();

protected:
    void dragEnterEvent(QDragEnterEvent *event);
    void dropEvent(QDropEvent *event);

private:
    bool readFile(const QString &fileName);
    QTextEdit *textEdit;
};
Drag file onto Window (2/4)
       MainWindow::MainWindow()
       {
           textEdit = new QTextEdit;
           setCentralWidget(textEdit);

           textEdit->setAcceptDrops(false);
           setAcceptDrops(true);

           setWindowTitle(tr("Text Editor"));
       }


QTextEdit
setAcceptDrops(false)
                setAcceptDrops(true)
                      MainWindow
Drag file onto Window (3/4)
 void MainWindow::dragEnterEvent(QDragEnterEvent *event)
 {
     if (event->mimeData()->hasFormat("text/plain"))
         event->acceptProposedAction();
 }


Standard MIME types are defined by the Internet Assigned
Numbers Authority (IANA). They consist of a type and a subtype
separated by a slash.

The official list of MIME types is available at http://www.iana.org/
assignments/media-types/
Drag file onto Window (4/4)

void MainWindow::dropEvent(QDropEvent *event)
{
    QList<QUrl> urls = event->mimeData()->urls();
    if (urls.isEmpty())
        return;

    QString fileName = urls.first().toLocalFile();
    if (fileName.isEmpty())
        return;

    if (readFile(fileName))
        setWindowTitle(tr("%1 - %2").arg(fileName)
                                    .arg(tr("Drag File")));
}
Initiate a Drag and Accept a Drop
               (1/4)

• Create a QListWidget subclass that
  supports drag and drop
Initiate a Drag and Accept a Drop
               (2/4)
   class ProjectListWidget : public QListWidget
   {
       Q_OBJECT

   public:
       ProjectListWidget(QWidget *parent = 0);

   protected:
       void mousePressEvent(QMouseEvent *event);
       void mouseMoveEvent(QMouseEvent *event);
       void dragEnterEvent(QDragEnterEvent *event);
       void dragMoveEvent(QDragMoveEvent *event);
       void dropEvent(QDropEvent *event);

   private:
       void performDrag();                        QWidget
                                       5
        QPoint startPos;
   };
Initiate a Drag and Accept a Drop
               (3/4)
ProjectListWidget::ProjectListWidget(QWidget *parent)
    : QListWidget(parent)
{
    setAcceptDrops(true);
}

void ProjectListWidget::mousePressEvent(QMouseEvent *event)
{
    if (event->button() == Qt::LeftButton)
        startPos = event->pos();
    QListWidget::mousePressEvent(event);
}

void ProjectListWidget::mouseMoveEvent(QMouseEvent *event)
{
    if (event->buttons() & Qt::LeftButton) {
        int distance = (event->pos() - startPos).manhattanLength();
        if (distance >= QApplication::startDragDistance())
            performDrag();
    }
    QListWidget::mouseMoveEvent(event);
}
Initiate a Drag and Accept a Drop
                   (4/4)
void ProjectListWidget::performDrag()
{
    QListWidgetItem *item = currentItem();
    if (item) {
        QMimeData *mimeData = new QMimeData;
        mimeData->setText(item->text());

         QDrag *drag = new QDrag(this);
         drag->setMimeData(mimeData);                QDrag
         drag->setPixmap(QPixmap(":/images/person.png"));
         if (drag->exec(Qt::MoveAction) == Qt::MoveAction)
             delete item;
     }                       QDrag::exec()
}
void ProjectListWidget::dragEnterEvent(QDragEnterEvent *event)
{
                                          ProjectListWidget
    ProjectListWidget *source =
            qobject_cast<ProjectListWidget *>(event->source());
    if (source && source != this) {
        event->setDropAction(Qt::MoveAction);
        event->accept();
    }
}

void ProjectListWidget::dropEvent(QDropEvent *event)
{
    ProjectListWidget *source =
            qobject_cast<ProjectListWidget *>(event->source());
    if (source && source != this) {
        addItem(event->mimeData()->text());
        event->setDropAction(Qt::MoveAction);
        event->accept();
    }
}
Drag custom data (1/2)
1. Provide arbitrary data as a QByteArray using
   QMimeData::setData() and extract it later
   using QMimeData::data()
2. Subclass QMimeData and re-implement
   formats() and retrieveData() to handle our
   custom data types
3. For drag and drop operations within a
   single application, we can subclass
   QMimeData and store the data using any
   data structure we want
Drag custom data (2/2)

• Drawbacks of Method 1
 ‣ Need	
  to	
  convert	
  our	
  data	
  structure	
  to	
  a	
  
      QByteArray	
  even	
  if	
  the	
  drag	
  is	
  not	
  ul1mately	
  
      accepted
 ‣ Providing	
  several	
  MIME	
  types	
  to	
  interact	
  nicely	
  
      with	
  a	
  wide	
  range	
  of	
  applica=ons,	
  we	
  need	
  to	
  
      store	
  the	
  data	
  several	
  1mes
 ‣ If	
  the	
  data	
  is	
  large,	
  this	
  can	
  slow	
  down	
  the	
  
      applica1on	
  needlessly
Add drag and drop capabilities to a
          QTableWidget (1/3)

   • Method 1
void MyTableWidget::mouseMoveEvent(QMouseEvent *event)
{
    if (event->buttons() & Qt::LeftButton) {
        int distance = (event->pos() - startPos).manhattanLength();
        if (distance >= QApplication::startDragDistance())
            performDrag();
    }
    QTableWidget::mouseMoveEvent(event);
}
Add drag and drop capabilities to a
              QTableWidget (2/3)
void MyTableWidget::performDrag()
{
    QString plainText = selectionAsPlainText();   Chap4 (p.87)
    if (plainText.isEmpty())
        return;

    QMimeData *mimeData = new QMimeData;
    mimeData->setText(plainText);
    mimeData->setHtml(toHtml(plainText));
    mimeData->setData("text/csv", toCsv(plainText).toUtf8());

    QDrag *drag = new QDrag(this);
    drag->setMimeData(mimeData);
    if (drag->exec(Qt::CopyAction | Qt::MoveAction) == Qt::MoveAction)
        deleteSelection();
}
Add drag and drop capabilities to a
          QTableWidget (3/3)
void MyTableWidget::dropEvent(QDropEvent *event)
{
    if (event->mimeData()->hasFormat("text/csv")) {
        QByteArray csvData = event->mimeData()->data("text/csv");
        QString csvText = QString::fromUtf8(csvData);
        ...
        event->acceptProposedAction();
    } else if (event->mimeData()->hasFormat("text/plain")) {
        QString plainText = event->mimeData()->text();
        ...
        event->acceptProposedAction();
    }
}
           QTableWidget         Html       OK
Subclass QMimeData (1/3)
class TableMimeData : public QMimeData
{
    Q_OBJECT

public:
    TableMimeData(const QTableWidget *tableWidget,
                  const QTableWidgetSelectionRange &range);

     const QTableWidget *tableWidget() const { return myTableWidget; }
     QTableWidgetSelectionRange range() const { return myRange; }
     QStringList formats() const;

protected:
    QVariant retrieveData(const QString &format,
                          QVariant::Type preferredType) const;

private:
    static QString toHtml(const QString &plainText);
    static QString toCsv(const QString &plainText);

     QString text(int row, int column) const;
     QString rangeAsPlainText() const;

     const QTableWidget *myTableWidget;                          ,
     QTableWidgetSelectionRange myRange;
     QStringList myFormats;                 QTableWidget                 ,
};
Subclass QMimeData (2/3)
TableMimeData::TableMimeData(const QTableWidget *tableWidget,
                             const QTableWidgetSelectionRange &range) {
    myTableWidget = tableWidget;
    myRange = range;
    myFormats << "text/csv" << "text/html" << "text/plain";
}

QStringList TableMimeData::formats() const {
    return myFormats;
}

QVariant TableMimeData::retrieveData(const QString &format,
                                      QVariant::Type preferredType) const {
    if (format == "text/plain")
         return rangeAsPlainText();
    else if (format == "text/csv")
         return toCsv(rangeAsPlainText());
    else if (format == "text/html") {
         return toHtml(rangeAsPlainText());
    else
         return QMimeData::retrieveData(format, preferredType);
}
Subclass QMimeData (3/3)
void MyTableWidget::dropEvent(QDropEvent *event)
{
    const TableMimeData *tableData =
            qobject_cast<const TableMimeData *>(event->mimeData());

    if (tableData) {
        const QTableWidget *otherTable = tableData->tableWidget();
        QTableWidgetSelectionRange otherRange = tableData->range();
        ...
        event->acceptProposedAction();
    } else if (event->mimeData()->hasFormat("text/csv")) {
        QByteArray csvData = event->mimeData()->data("text/csv");
        QString csvText = QString::fromUtf8(csvData);
        ...

                                           we can directly access the table
    }
    QTableWidget::mouseMoveEvent(event);   data instead of going through
                                           QMimeData's API
}
Clipboard Handling

• Access clipboard: QApplication::clipboard()
• Built-in functionality might not be sufficient
   (not just text or an image)
  ‣ Subclass	
  QMimeData	
  and	
  re-­‐implement	
  a	
  few	
  virtual	
  
       func=ons	
  
  ‣ Reuse	
  the	
  QMimeData	
  subclass	
  and	
  put	
  it	
  on	
  the	
  
       clipboard	
  using	
  the	
  setMimeData()	
  func=on.	
  To	
  retrieve	
  
       the	
  data,	
  we	
  can	
  call	
  mimeData()	
  on	
  the	
  clipboard

• Clipboard's contents change
  ‣ QClipboard::dataChanged()	
  signal
Thank you :)
Ad

Recommended

PDF
05 - Qt External Interaction and Graphics
Andreas Jakl
 
PPTX
Beginning direct3d gameprogrammingcpp02_20160324_jintaeks
JinTaek Seo
 
PPT
Ken 20150306 心得分享
LearningTech
 
KEY
Web Grafik Technologien
n3xd software studios ag
 
PDF
The Ring programming language version 1.10 book - Part 82 of 212
Mahmoud Samir Fayed
 
PPTX
Rxjs ngvikings
Christoffer Noring
 
PDF
Experiments with C++11
Andreas Bærentzen
 
PDF
J S B6 Ref Booklet
51 lecture
 
PPTX
Angular2 rxjs
Christoffer Noring
 
PDF
The Ring programming language version 1.10 book - Part 106 of 212
Mahmoud Samir Fayed
 
PDF
Sustaining Test-Driven Development
AgileOnTheBeach
 
PDF
The Ring programming language version 1.5.3 book - Part 8 of 184
Mahmoud Samir Fayed
 
PDF
The Ring programming language version 1.5 book - Part 12 of 31
Mahmoud Samir Fayed
 
PDF
The Ring programming language version 1.5.4 book - Part 8 of 185
Mahmoud Samir Fayed
 
PDF
The Ring programming language version 1.5.1 book - Part 7 of 180
Mahmoud Samir Fayed
 
PDF
The Ring programming language version 1.5.1 book - Part 12 of 180
Mahmoud Samir Fayed
 
PPTX
Rxjs ppt
Christoffer Noring
 
PDF
Rxjs vienna
Christoffer Noring
 
PDF
AJUG April 2011 Cascading example
Christopher Curtin
 
PDF
Vaadin 7 Today and Tomorrow
Joonas Lehtinen
 
PDF
The Ring programming language version 1.7 book - Part 101 of 196
Mahmoud Samir Fayed
 
PPTX
KDD 2016 Streaming Analytics Tutorial
Neera Agarwal
 
PPTX
OpenMAMA Under the Hood
OpenMAMA
 
PDF
Vaadin today and tomorrow
Joonas Lehtinen
 
PDF
The Ring programming language version 1.9 book - Part 74 of 210
Mahmoud Samir Fayed
 
PDF
The Ring programming language version 1.8 book - Part 71 of 202
Mahmoud Samir Fayed
 
DOC
Qtp+real time+test+script
Ramu Palanki
 
PDF
The Ring programming language version 1.9 book - Part 103 of 210
Mahmoud Samir Fayed
 
PDF
The Ring programming language version 1.9 book - Part 96 of 210
Mahmoud Samir Fayed
 
PDF
The Ring programming language version 1.7 book - Part 105 of 196
Mahmoud Samir Fayed
 

More Related Content

What's hot (19)

PPTX
Angular2 rxjs
Christoffer Noring
 
PDF
The Ring programming language version 1.10 book - Part 106 of 212
Mahmoud Samir Fayed
 
PDF
Sustaining Test-Driven Development
AgileOnTheBeach
 
PDF
The Ring programming language version 1.5.3 book - Part 8 of 184
Mahmoud Samir Fayed
 
PDF
The Ring programming language version 1.5 book - Part 12 of 31
Mahmoud Samir Fayed
 
PDF
The Ring programming language version 1.5.4 book - Part 8 of 185
Mahmoud Samir Fayed
 
PDF
The Ring programming language version 1.5.1 book - Part 7 of 180
Mahmoud Samir Fayed
 
PDF
The Ring programming language version 1.5.1 book - Part 12 of 180
Mahmoud Samir Fayed
 
PPTX
Rxjs ppt
Christoffer Noring
 
PDF
Rxjs vienna
Christoffer Noring
 
PDF
AJUG April 2011 Cascading example
Christopher Curtin
 
PDF
Vaadin 7 Today and Tomorrow
Joonas Lehtinen
 
PDF
The Ring programming language version 1.7 book - Part 101 of 196
Mahmoud Samir Fayed
 
PPTX
KDD 2016 Streaming Analytics Tutorial
Neera Agarwal
 
PPTX
OpenMAMA Under the Hood
OpenMAMA
 
PDF
Vaadin today and tomorrow
Joonas Lehtinen
 
PDF
The Ring programming language version 1.9 book - Part 74 of 210
Mahmoud Samir Fayed
 
PDF
The Ring programming language version 1.8 book - Part 71 of 202
Mahmoud Samir Fayed
 
DOC
Qtp+real time+test+script
Ramu Palanki
 
Angular2 rxjs
Christoffer Noring
 
The Ring programming language version 1.10 book - Part 106 of 212
Mahmoud Samir Fayed
 
Sustaining Test-Driven Development
AgileOnTheBeach
 
The Ring programming language version 1.5.3 book - Part 8 of 184
Mahmoud Samir Fayed
 
The Ring programming language version 1.5 book - Part 12 of 31
Mahmoud Samir Fayed
 
The Ring programming language version 1.5.4 book - Part 8 of 185
Mahmoud Samir Fayed
 
The Ring programming language version 1.5.1 book - Part 7 of 180
Mahmoud Samir Fayed
 
The Ring programming language version 1.5.1 book - Part 12 of 180
Mahmoud Samir Fayed
 
Rxjs vienna
Christoffer Noring
 
AJUG April 2011 Cascading example
Christopher Curtin
 
Vaadin 7 Today and Tomorrow
Joonas Lehtinen
 
The Ring programming language version 1.7 book - Part 101 of 196
Mahmoud Samir Fayed
 
KDD 2016 Streaming Analytics Tutorial
Neera Agarwal
 
OpenMAMA Under the Hood
OpenMAMA
 
Vaadin today and tomorrow
Joonas Lehtinen
 
The Ring programming language version 1.9 book - Part 74 of 210
Mahmoud Samir Fayed
 
The Ring programming language version 1.8 book - Part 71 of 202
Mahmoud Samir Fayed
 
Qtp+real time+test+script
Ramu Palanki
 

Similar to [C++ gui programming with qt4] chap9 (7)

PDF
The Ring programming language version 1.9 book - Part 103 of 210
Mahmoud Samir Fayed
 
PDF
The Ring programming language version 1.9 book - Part 96 of 210
Mahmoud Samir Fayed
 
PDF
The Ring programming language version 1.7 book - Part 105 of 196
Mahmoud Samir Fayed
 
PDF
The Ring programming language version 1.4.1 book - Part 28 of 31
Mahmoud Samir Fayed
 
ODP
Dn d clipboard
pinnamur
 
ODP
Dn d clipboard
pinnamur
 
ODP
Dn d clipboard
pinnamur
 
The Ring programming language version 1.9 book - Part 103 of 210
Mahmoud Samir Fayed
 
The Ring programming language version 1.9 book - Part 96 of 210
Mahmoud Samir Fayed
 
The Ring programming language version 1.7 book - Part 105 of 196
Mahmoud Samir Fayed
 
The Ring programming language version 1.4.1 book - Part 28 of 31
Mahmoud Samir Fayed
 
Dn d clipboard
pinnamur
 
Dn d clipboard
pinnamur
 
Dn d clipboard
pinnamur
 
Ad

More from Shih-Hsiang Lin (13)

PDF
Introduction to Apache Ant
Shih-Hsiang Lin
 
PDF
Introduction to GNU Make Programming Language
Shih-Hsiang Lin
 
KEY
Ch6 file, saving states, and preferences
Shih-Hsiang Lin
 
PDF
Ch5 intent broadcast receivers adapters and internet
Shih-Hsiang Lin
 
PDF
Ch4 creating user interfaces
Shih-Hsiang Lin
 
PDF
Ch3 creating application and activities
Shih-Hsiang Lin
 
PDF
[C++ GUI Programming with Qt4] chap7
Shih-Hsiang Lin
 
PPTX
[C++ GUI Programming with Qt4] chap4
Shih-Hsiang Lin
 
PPTX
Function pointer
Shih-Hsiang Lin
 
PPT
Introduction to homography
Shih-Hsiang Lin
 
PPTX
Git basic
Shih-Hsiang Lin
 
PPTX
Project Hosting by Google
Shih-Hsiang Lin
 
PDF
An Introduction to Hidden Markov Model
Shih-Hsiang Lin
 
Introduction to Apache Ant
Shih-Hsiang Lin
 
Introduction to GNU Make Programming Language
Shih-Hsiang Lin
 
Ch6 file, saving states, and preferences
Shih-Hsiang Lin
 
Ch5 intent broadcast receivers adapters and internet
Shih-Hsiang Lin
 
Ch4 creating user interfaces
Shih-Hsiang Lin
 
Ch3 creating application and activities
Shih-Hsiang Lin
 
[C++ GUI Programming with Qt4] chap7
Shih-Hsiang Lin
 
[C++ GUI Programming with Qt4] chap4
Shih-Hsiang Lin
 
Function pointer
Shih-Hsiang Lin
 
Introduction to homography
Shih-Hsiang Lin
 
Git basic
Shih-Hsiang Lin
 
Project Hosting by Google
Shih-Hsiang Lin
 
An Introduction to Hidden Markov Model
Shih-Hsiang Lin
 
Ad

Recently uploaded (20)

PPTX
June 2025 Progress Update With Board Call_In process.pptx
International Society of Service Innovation Professionals
 
PPTX
A Visual Introduction to the Prophet Jeremiah
Steve Thomason
 
PPTX
F-BLOCK ELEMENTS POWER POINT PRESENTATIONS
mprpgcwa2024
 
PPTX
Peer Teaching Observations During School Internship
AjayaMohanty7
 
PDF
University of Ghana Cracks Down on Misconduct: Over 100 Students Sanctioned
Kweku Zurek
 
PPTX
IIT KGP Quiz Week 2024 Sports Quiz (Prelims + Finals)
IIT Kharagpur Quiz Club
 
PPTX
Values Education 10 Quarter 1 Module .pptx
JBPafin
 
PDF
K12 Tableau User Group virtual event June 18, 2025
dogden2
 
PPTX
Code Profiling in Odoo 18 - Odoo 18 Slides
Celine George
 
PPTX
ENGLISH-5 Q1 Lesson 1.pptx - Story Elements
Mayvel Nadal
 
PPTX
Filipino 9 Maikling Kwento Ang Ama Panitikang Asiyano
sumadsadjelly121997
 
PPTX
How to use _name_search() method in Odoo 18
Celine George
 
PPTX
GREAT QUIZ EXCHANGE 2025 - GENERAL QUIZ.pptx
Ronisha Das
 
PPTX
How to Manage Different Customer Addresses in Odoo 18 Accounting
Celine George
 
PDF
Aprendendo Arquitetura Framework Salesforce - Dia 02
Mauricio Alexandre Silva
 
PPTX
How payment terms are configured in Odoo 18
Celine George
 
PPTX
Birnagar High School Platinum Jubilee Quiz.pptx
Sourav Kr Podder
 
PPTX
List View Components in Odoo 18 - Odoo Slides
Celine George
 
PDF
VCE Literature Section A Exam Response Guide
jpinnuck
 
PDF
Romanticism in Love and Sacrifice An Analysis of Oscar Wilde’s The Nightingal...
KaryanaTantri21
 
June 2025 Progress Update With Board Call_In process.pptx
International Society of Service Innovation Professionals
 
A Visual Introduction to the Prophet Jeremiah
Steve Thomason
 
F-BLOCK ELEMENTS POWER POINT PRESENTATIONS
mprpgcwa2024
 
Peer Teaching Observations During School Internship
AjayaMohanty7
 
University of Ghana Cracks Down on Misconduct: Over 100 Students Sanctioned
Kweku Zurek
 
IIT KGP Quiz Week 2024 Sports Quiz (Prelims + Finals)
IIT Kharagpur Quiz Club
 
Values Education 10 Quarter 1 Module .pptx
JBPafin
 
K12 Tableau User Group virtual event June 18, 2025
dogden2
 
Code Profiling in Odoo 18 - Odoo 18 Slides
Celine George
 
ENGLISH-5 Q1 Lesson 1.pptx - Story Elements
Mayvel Nadal
 
Filipino 9 Maikling Kwento Ang Ama Panitikang Asiyano
sumadsadjelly121997
 
How to use _name_search() method in Odoo 18
Celine George
 
GREAT QUIZ EXCHANGE 2025 - GENERAL QUIZ.pptx
Ronisha Das
 
How to Manage Different Customer Addresses in Odoo 18 Accounting
Celine George
 
Aprendendo Arquitetura Framework Salesforce - Dia 02
Mauricio Alexandre Silva
 
How payment terms are configured in Odoo 18
Celine George
 
Birnagar High School Platinum Jubilee Quiz.pptx
Sourav Kr Podder
 
List View Components in Odoo 18 - Odoo Slides
Celine George
 
VCE Literature Section A Exam Response Guide
jpinnuck
 
Romanticism in Love and Sacrifice An Analysis of Oscar Wilde’s The Nightingal...
KaryanaTantri21
 

[C++ gui programming with qt4] chap9

  • 1. Ch9.Drag and Drop Browny 23, May, 2011
  • 2. Outline • Enabling Drag and Drop • Supporting Custom Drag Types • Clipboard Handling
  • 3. Drag file onto Window (1/4) class MainWindow : public QMainWindow { Q_OBJECT public: MainWindow(); protected: void dragEnterEvent(QDragEnterEvent *event); void dropEvent(QDropEvent *event); private: bool readFile(const QString &fileName); QTextEdit *textEdit; };
  • 4. Drag file onto Window (2/4) MainWindow::MainWindow() { textEdit = new QTextEdit; setCentralWidget(textEdit); textEdit->setAcceptDrops(false); setAcceptDrops(true); setWindowTitle(tr("Text Editor")); } QTextEdit setAcceptDrops(false) setAcceptDrops(true) MainWindow
  • 5. Drag file onto Window (3/4) void MainWindow::dragEnterEvent(QDragEnterEvent *event) { if (event->mimeData()->hasFormat("text/plain")) event->acceptProposedAction(); } Standard MIME types are defined by the Internet Assigned Numbers Authority (IANA). They consist of a type and a subtype separated by a slash. The official list of MIME types is available at http://www.iana.org/ assignments/media-types/
  • 6. Drag file onto Window (4/4) void MainWindow::dropEvent(QDropEvent *event) { QList<QUrl> urls = event->mimeData()->urls(); if (urls.isEmpty()) return; QString fileName = urls.first().toLocalFile(); if (fileName.isEmpty()) return; if (readFile(fileName)) setWindowTitle(tr("%1 - %2").arg(fileName) .arg(tr("Drag File"))); }
  • 7. Initiate a Drag and Accept a Drop (1/4) • Create a QListWidget subclass that supports drag and drop
  • 8. Initiate a Drag and Accept a Drop (2/4) class ProjectListWidget : public QListWidget { Q_OBJECT public: ProjectListWidget(QWidget *parent = 0); protected: void mousePressEvent(QMouseEvent *event); void mouseMoveEvent(QMouseEvent *event); void dragEnterEvent(QDragEnterEvent *event); void dragMoveEvent(QDragMoveEvent *event); void dropEvent(QDropEvent *event); private: void performDrag(); QWidget 5 QPoint startPos; };
  • 9. Initiate a Drag and Accept a Drop (3/4) ProjectListWidget::ProjectListWidget(QWidget *parent) : QListWidget(parent) { setAcceptDrops(true); } void ProjectListWidget::mousePressEvent(QMouseEvent *event) { if (event->button() == Qt::LeftButton) startPos = event->pos(); QListWidget::mousePressEvent(event); } void ProjectListWidget::mouseMoveEvent(QMouseEvent *event) { if (event->buttons() & Qt::LeftButton) { int distance = (event->pos() - startPos).manhattanLength(); if (distance >= QApplication::startDragDistance()) performDrag(); } QListWidget::mouseMoveEvent(event); }
  • 10. Initiate a Drag and Accept a Drop (4/4) void ProjectListWidget::performDrag() { QListWidgetItem *item = currentItem(); if (item) { QMimeData *mimeData = new QMimeData; mimeData->setText(item->text()); QDrag *drag = new QDrag(this); drag->setMimeData(mimeData); QDrag drag->setPixmap(QPixmap(":/images/person.png")); if (drag->exec(Qt::MoveAction) == Qt::MoveAction) delete item; } QDrag::exec() }
  • 11. void ProjectListWidget::dragEnterEvent(QDragEnterEvent *event) { ProjectListWidget ProjectListWidget *source = qobject_cast<ProjectListWidget *>(event->source()); if (source && source != this) { event->setDropAction(Qt::MoveAction); event->accept(); } } void ProjectListWidget::dropEvent(QDropEvent *event) { ProjectListWidget *source = qobject_cast<ProjectListWidget *>(event->source()); if (source && source != this) { addItem(event->mimeData()->text()); event->setDropAction(Qt::MoveAction); event->accept(); } }
  • 12. Drag custom data (1/2) 1. Provide arbitrary data as a QByteArray using QMimeData::setData() and extract it later using QMimeData::data() 2. Subclass QMimeData and re-implement formats() and retrieveData() to handle our custom data types 3. For drag and drop operations within a single application, we can subclass QMimeData and store the data using any data structure we want
  • 13. Drag custom data (2/2) • Drawbacks of Method 1 ‣ Need  to  convert  our  data  structure  to  a   QByteArray  even  if  the  drag  is  not  ul1mately   accepted ‣ Providing  several  MIME  types  to  interact  nicely   with  a  wide  range  of  applica=ons,  we  need  to   store  the  data  several  1mes ‣ If  the  data  is  large,  this  can  slow  down  the   applica1on  needlessly
  • 14. Add drag and drop capabilities to a QTableWidget (1/3) • Method 1 void MyTableWidget::mouseMoveEvent(QMouseEvent *event) { if (event->buttons() & Qt::LeftButton) { int distance = (event->pos() - startPos).manhattanLength(); if (distance >= QApplication::startDragDistance()) performDrag(); } QTableWidget::mouseMoveEvent(event); }
  • 15. Add drag and drop capabilities to a QTableWidget (2/3) void MyTableWidget::performDrag() { QString plainText = selectionAsPlainText(); Chap4 (p.87) if (plainText.isEmpty()) return; QMimeData *mimeData = new QMimeData; mimeData->setText(plainText); mimeData->setHtml(toHtml(plainText)); mimeData->setData("text/csv", toCsv(plainText).toUtf8()); QDrag *drag = new QDrag(this); drag->setMimeData(mimeData); if (drag->exec(Qt::CopyAction | Qt::MoveAction) == Qt::MoveAction) deleteSelection(); }
  • 16. Add drag and drop capabilities to a QTableWidget (3/3) void MyTableWidget::dropEvent(QDropEvent *event) { if (event->mimeData()->hasFormat("text/csv")) { QByteArray csvData = event->mimeData()->data("text/csv"); QString csvText = QString::fromUtf8(csvData); ... event->acceptProposedAction(); } else if (event->mimeData()->hasFormat("text/plain")) { QString plainText = event->mimeData()->text(); ... event->acceptProposedAction(); } } QTableWidget Html OK
  • 17. Subclass QMimeData (1/3) class TableMimeData : public QMimeData { Q_OBJECT public: TableMimeData(const QTableWidget *tableWidget, const QTableWidgetSelectionRange &range); const QTableWidget *tableWidget() const { return myTableWidget; } QTableWidgetSelectionRange range() const { return myRange; } QStringList formats() const; protected: QVariant retrieveData(const QString &format, QVariant::Type preferredType) const; private: static QString toHtml(const QString &plainText); static QString toCsv(const QString &plainText); QString text(int row, int column) const; QString rangeAsPlainText() const; const QTableWidget *myTableWidget; , QTableWidgetSelectionRange myRange; QStringList myFormats; QTableWidget , };
  • 18. Subclass QMimeData (2/3) TableMimeData::TableMimeData(const QTableWidget *tableWidget, const QTableWidgetSelectionRange &range) { myTableWidget = tableWidget; myRange = range; myFormats << "text/csv" << "text/html" << "text/plain"; } QStringList TableMimeData::formats() const { return myFormats; } QVariant TableMimeData::retrieveData(const QString &format, QVariant::Type preferredType) const { if (format == "text/plain") return rangeAsPlainText(); else if (format == "text/csv") return toCsv(rangeAsPlainText()); else if (format == "text/html") { return toHtml(rangeAsPlainText()); else return QMimeData::retrieveData(format, preferredType); }
  • 19. Subclass QMimeData (3/3) void MyTableWidget::dropEvent(QDropEvent *event) { const TableMimeData *tableData = qobject_cast<const TableMimeData *>(event->mimeData()); if (tableData) { const QTableWidget *otherTable = tableData->tableWidget(); QTableWidgetSelectionRange otherRange = tableData->range(); ... event->acceptProposedAction(); } else if (event->mimeData()->hasFormat("text/csv")) { QByteArray csvData = event->mimeData()->data("text/csv"); QString csvText = QString::fromUtf8(csvData); ... we can directly access the table } QTableWidget::mouseMoveEvent(event); data instead of going through QMimeData's API }
  • 20. Clipboard Handling • Access clipboard: QApplication::clipboard() • Built-in functionality might not be sufficient (not just text or an image) ‣ Subclass  QMimeData  and  re-­‐implement  a  few  virtual   func=ons   ‣ Reuse  the  QMimeData  subclass  and  put  it  on  the   clipboard  using  the  setMimeData()  func=on.  To  retrieve   the  data,  we  can  call  mimeData()  on  the  clipboard • Clipboard's contents change ‣ QClipboard::dataChanged()  signal