[C++ gui programming with qt4] chap9
Upcoming SlideShare
Loading in...5
×

Like this? Share it with your network

Share
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Be the first to comment
No Downloads

Views

Total Views
1,605
On Slideshare
1,605
From Embeds
0
Number of Embeds
0

Actions

Shares
Downloads
53
Comments
0
Likes
1

Embeds 0

No embeds

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
    No notes for slide

Transcript

  • 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_OBJECTpublic: 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")); }QTextEditsetAcceptDrops(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 AssignedNumbers Authority (IANA). They consist of a type and a subtypeseparated 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 types3. 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 1void 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_OBJECTpublic: 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 QMimeDatas 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• Clipboards contents change ‣ QClipboard::dataChanged()  signal
  • 21. Thank you :)