- Любовные романы
- Фантастика и фэнтези
- Ненаучная фантастика
- Ироническое фэнтези
- Научная Фантастика
- Фэнтези
- Ужасы и Мистика
- Боевая фантастика
- Альтернативная история
- Космическая фантастика
- Попаданцы
- Юмористическая фантастика
- Героическая фантастика
- Детективная фантастика
- Социально-психологическая
- Боевое фэнтези
- Русское фэнтези
- Киберпанк
- Романтическая фантастика
- Городская фантастика
- Технофэнтези
- Мистика
- Разная фантастика
- Иностранное фэнтези
- Историческое фэнтези
- LitRPG
- Эпическая фантастика
- Зарубежная фантастика
- Городское фентези
- Космоопера
- Разное фэнтези
- Книги магов
- Любовное фэнтези
- Постапокалипсис
- Бизнес
- Историческая фантастика
- Социально-философская фантастика
- Сказочная фантастика
- Стимпанк
- Романтическое фэнтези
- Ироническая фантастика
- Детективы и Триллеры
- Проза
- Юмор
- Феерия
- Новелла
- Русская классическая проза
- Современная проза
- Повести
- Контркультура
- Русская современная проза
- Историческая проза
- Проза
- Классическая проза
- Советская классическая проза
- О войне
- Зарубежная современная проза
- Рассказы
- Зарубежная классика
- Очерки
- Антисоветская литература
- Магический реализм
- Разное
- Сентиментальная проза
- Афоризмы
- Эссе
- Эпистолярная проза
- Семейный роман/Семейная сага
- Поэзия, Драматургия
- Приключения
- Детская литература
- Загадки
- Книга-игра
- Детская проза
- Детские приключения
- Сказка
- Прочая детская литература
- Детская фантастика
- Детские стихи
- Детская образовательная литература
- Детские остросюжетные
- Учебная литература
- Зарубежные детские книги
- Детский фольклор
- Буквари
- Книги для подростков
- Школьные учебники
- Внеклассное чтение
- Книги для дошкольников
- Детская познавательная и развивающая литература
- Детские детективы
- Домоводство, Дом и семья
- Юмор
- Документальные книги
- Бизнес
- Работа с клиентами
- Тайм-менеджмент
- Кадровый менеджмент
- Экономика
- Менеджмент и кадры
- Управление, подбор персонала
- О бизнесе популярно
- Интернет-бизнес
- Личные финансы
- Делопроизводство, офис
- Маркетинг, PR, реклама
- Поиск работы
- Бизнес
- Банковское дело
- Малый бизнес
- Ценные бумаги и инвестиции
- Краткое содержание
- Бухучет и аудит
- Ораторское искусство / риторика
- Корпоративная культура, бизнес
- Финансы
- Государственное и муниципальное управление
- Менеджмент
- Зарубежная деловая литература
- Продажи
- Переговоры
- Личная эффективность
- Торговля
- Научные и научно-популярные книги
- Биофизика
- География
- Экология
- Биохимия
- Рефераты
- Культурология
- Техническая литература
- История
- Психология
- Медицина
- Прочая научная литература
- Юриспруденция
- Биология
- Политика
- Литературоведение
- Религиоведение
- Научпоп
- Психология, личное
- Математика
- Психотерапия
- Социология
- Воспитание детей, педагогика
- Языкознание
- Беременность, ожидание детей
- Транспорт, военная техника
- Детская психология
- Науки: разное
- Педагогика
- Зарубежная психология
- Иностранные языки
- Филология
- Радиотехника
- Деловая литература
- Физика
- Альтернативная медицина
- Химия
- Государство и право
- Обществознание
- Образовательная литература
- Учебники
- Зоология
- Архитектура
- Науки о космосе
- Ботаника
- Астрология
- Ветеринария
- История Европы
- География
- Зарубежная публицистика
- О животных
- Шпаргалки
- Разная литература
- Зарубежная литература о культуре и искусстве
- Пословицы, поговорки
- Боевые искусства
- Прочее
- Периодические издания
- Фанфик
- Военное
- Цитаты из афоризмов
- Гиды, путеводители
- Литература 19 века
- Зарубежная образовательная литература
- Военная история
- Кино
- Современная литература
- Военная техника, оружие
- Культура и искусство
- Музыка, музыканты
- Газеты и журналы
- Современная зарубежная литература
- Визуальные искусства
- Отраслевые издания
- Шахматы
- Недвижимость
- Великолепные истории
- Музыка, танцы
- Авто и ПДД
- Изобразительное искусство, фотография
- Истории из жизни
- Готические новеллы
- Начинающие авторы
- Спецслужбы
- Подростковая литература
- Зарубежная прикладная литература
- Религия и духовность
- Старинная литература
- Справочная литература
- Компьютеры и Интернет
- Блог
QT 4: программирование GUI на С++ - Жасмин Бланшет
Шрифт:
Интервал:
Закладка:
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;
11 }
12 QString MyTableWidget::toHtml(const QString &plainText)
13 {
14 QString result = Qt::escape(plainText);
15 result.replace("t", "<td>");
16 result.replace("n", "n<tr><td>");
17 result.prepend("<table>n<tr><td>");
18 result.append("n</table>");
19 return result;
20 }
Функции toCsv() и toHtml() преобразуют строку со знаками табуляции и конца строки в формат CSV (comma—separated values — значения, разделенные запятыми) и HTML соответственно. Например, данные
Red Green Blue
Cyan Yellow Magenta
преобразуются в
"Red", "Green", "Blue"
"Cyan", "Yellow", "Magenta"
или в
<table>
<tr><td>Red<td>Green<td>Blue
<tr><td>Cyan<td>Yellow<td>Magenta
</table>
Преобразование выполняется самым простым из возможных способов с применением функции QString::replace(). Для удаления специальных символов формата HTML мы используем функцию Qt::escape().
01 void MyTableWidget::dropEvent(QDropEvent *event)
02 {
03 if (event->mimeData()->hasFormat("text/csv")) {
04 QByteArray csvData = event->mimeData()->data("text/csv");
05 QString csvText = QString::fromUtf8(csvData);
06 …
07 event->acceptProposedAction();
08 } else if (event->mimeData()->hasFormat("text/plain")) {
09 QString plainText = event->mimeData()->text();
10 …
11 event->acceptProposedAction();
12 }
13 }
Хотя мы предоставляем данные в трех разных форматах, мы принимаем в dropEvent() только два из них. Если подьзователь переносит ячейки из таблицы QTableWidget в редактор HTML, нам нужно, чтобы ячейки были преобразованы в таблицу HTML. Но если пользователь переносит произвольный текст HTML в таблицу QTableWidget, мы не станем его принимать.
Для того чтобы этот пример заработал, нам потребуется также вызвать setAcceptDrops(true) и setSelectionMode(ContiguousSelection) в конструкторе MyTableWidget.
Теперь мы переделаем этот пример, но на этот раз мы создадим подкласс QMimeData, чтобы отложить или избежать (потенциально затратных) преобразований между элементами QTableWidgetltem и массивом QByteArray. Ниже приводится определение нашего подкласса:
01 class TableMimeData : public QMimeData
02 {
03 Q_OBJECT
04 public:
05 TableMimeData(const QTableWidget *tableWidget,
06 const QTableWidgetSelectionRange &range);
07 const QTableWidget *tableWidget() const
08 { return myTableWidget; }
09 QTableWidgetSelectionRange range() const { return myRange; }
10 QStringList formats() const;
11 protected:
12 QVariant retrieveData(const QString &format,
13 QVariant::Type preferredType) const;
14 private:
15 static QString toHtml(const QString &plainText);
16 static QString toCsv(const QString &plainText);
17 QString text(int row, int column) const;
18 QString rangeAsPlainText() const;
19 const QTableWidget *myTableWidget;
20 QTableWidgetSelectionRange myRange;
21 QStringList myFormats;
22 };
Вместо реальных данных мы храним объект QTableWidgetSelectionRange, который определяет область переносимых ячеек и сохраняет указатель на QTableWidget. Функции formats() и retrieveData() класса QMimeData переопределяются.
01 TableMimeData::TableMimeData(const QTableWidget *tableWidget,
02 const QTableWidgetSelectionRange &range)
03 {
04 myTableWidget = tableWidget;
05 myRange = range;
06 myFormats << "text/csv" << "text/html" << "text/plain";
07 }
В конструкторе мы инициализируем закрытые переменные.
01 QStringList TableMimeData::formats() const
02 {
03 return myFormats;
04 }
Функция formats() возвращает список MIME—типов, находящихся в объекте MIME—данных. Последовательность форматов обычно несущественна, однако на практике желательно первыми указывать «лучшие» форматы. Приложения, поддерживающие несколько форматов, иногда будут использовать первый подходящий.

