Чтение онлайн

ЖАНРЫ

QT 4: программирование GUI на С++

Саммерфилд Марк

Шрифт:

01 void ProjectListWidget::dragMoveEvent(QDragMoveEvent *event)

02 {

03 ProjectListWidget *source =

04 qobject_cast<ProjectListWidget *>(event->source);

05 if (source && source != this) {

07 event->setDropAction(Qt::MoveAction);

08 event->accept;

09 }

10 }

Программный код функции dragMoveEvent идентичен тому, что мы делали в функции dragEnterEvent.

Он необходим, потому что нам приходится переопределять реализацию этой функции в классе QListWidget (в действительности в классе QAbstractItemView).

01 void ProjectListWidget::dropEvent(QDropEvent *event)

02 {

03 ProjectListWidget *source =

04 qobject_cast<ProjectListWidget *>(event->source);

05 if (source && source != this) {

06 addItem(event->mimeData->text);

07 event->setDropAction(Qt::MoveAction);

08 event->accept;

09 }

10 }

В DropEvent мы используем функцию QMimeData::text для получения перенесенного текста и создаем элемент с этим текстом. Нам также необходимо воспринять данное событие как «операцию перетаскивания», чтобы указать исходному виджету на то, что он может теперь удалить первоначальную версию перенесенного элемента.

«Drag-and-drop» — мощный механизм передачи данных между приложениями. Однако в некоторых случаях его можно реализовать, не используя предусмотренные в Qt средства механизма «drag-and-drop». Если нам требуется переносить данные внутри одного виджета некоторого приложения, во многих случаях мы можем просто переопределить функции mousePressEvent и mouseReleaseEvent.

Поддержка пользовательских типов переносимых объектов

До сих пор в представленных примерах мы полагались на поддержку QMimeData распространенных типов MIME. Так, мы вызывали QMimeData::setText для создания объекта переноса текста и использовали QMimeData:urls для получения содержимого объекта переноса типа text/uri-list. Если мы хотим перетаскивать обычный текст, текст в формате HTML, изображения, адреса URL или цвета, мы можем спокойно использовать класс QMimeData. Но если мы хотим перетаскивать пользовательские данные, необходимо сделать выбор между следующими альтернативами:

1. Мы можем обеспечить произвольные данные в виде массива QByteArray, используя функцию QMimeData::setData, и извлекать их позже, используя функцию QMimeData::data.

2. Мы можем создать подкласс QMimeData и переопределить функции formats и retrieveData для обработки наших пользовательских типов данных.

3. Для выполнения операций механизма «drag-and-drop» в рамках одного приложения мы можем создать подкласс QMimeData и хранить данные в любых структурах данных.

Первый подход не требует никаких подклассов, но имеет некоторые недостатки: нам необходимо преобразбвать наши структуры данных в тип QByteArray, даже если переносимый объект не принимается, а если требуется обеспечить несколько MIME—типов, чтобы можно было хорошо взаимодействовать с самыми разными приложениями,

нам придется сохранять несколько копий данных (по одной на каждый тип MIME). Если данные имеют большой размер, это может излишне замедлять работу приложения. При использовании второго и третьего подходов можно избежать или свести к минимуму эти проблемы. В этом случае мы получаем полное управление и можем использовать эти два подхода совместно.

Для демонстрации этих подходов мы покажем, как можно добавить возможности технологии «drag-and-drop» в виджет QTableWidget. Будет поддерживаться перенос следующих типов MIME: text/plain, text/html и text/csv. При применении первого подхода инициирование переноса выглядит следующим образом:

01 void MyTableWidget::mouseMoveEvent(QMouseEvent *event)

02 {

03 if (event->buttons & Qt::LeftButton) {

04 int distance = (event->pos - startPos).manhattanLength;

05 if(distance >= QApplication::startDragDistance)

06 startDrag;

07 }

08 QTableWidget::mouseMoveEvent(event);

09 }

10 void MyTableWidget::startDrag

11 {

12 QString plainText= selectionAsPlainText;

13 if (plainText.isEmpty)

14 return;

15 QMimeData *mimeData = new QMimeData;

16 mimeData->setText(plainText);

17 mimeData->setHtml(toHtml(plainText));

18 mimeData->setData("text/csv", toCsv(plainText).toUtf8);

19 QDrag *drag = new QDrag(this);

20 drag->setMimeData(mimeData);

21 if (drag->start(Qt::CopyAction | Qt::MoveAction) == Qt::MoveAction)

22 deleteSelection;

23 }

Закрытая функция startDrag вызывается из mouseMoveEvent для инициирования переноса выделенной прямоугольной области. Мы устанавливаем типы MIME text/plain и text/html, используя функции setText и setHtml, а тип text/csv мы устанавливаем функцией setData, которая принимает произвольный тип MIME и массив QByteArray. Программный код для функции selectionAsString более или менее совпадает с кодом функции Spreadsheet::copy, рассмотренной в главе 4.

01 QString MyTableWidget::toCsv(const QString &plainText)

02 {

03 QString result = plainText;

04 result.replace("\\", "\\\\");

05 result.replace("\"", "\\\"");

06 result.replace("\t", "\", \"")

07 result.replace("\n", "\"\n\"");

08 result.prepend("\"");

09 result.append("\"");

10 return result;

Поделиться с друзьями: