PageRenderTime 56ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 0ms

/src/item/itemwidget.cpp

https://github.com/hluk/CopyQ
C++ | 304 lines | 224 code | 57 blank | 23 comment | 26 complexity | 628fd71ff40fa06a922abf691a96312b MD5 | raw file
Possible License(s): GPL-3.0, BSD-3-Clause
  1. /*
  2. Copyright (c) 2020, Lukas Holecek <hluk@email.cz>
  3. This file is part of CopyQ.
  4. CopyQ is free software: you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation, either version 3 of the License, or
  7. (at your option) any later version.
  8. CopyQ is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with CopyQ. If not, see <http://www.gnu.org/licenses/>.
  14. */
  15. #include "itemwidget.h"
  16. #include "common/command.h"
  17. #include "common/contenttype.h"
  18. #include "common/mimetypes.h"
  19. #include "item/itemeditor.h"
  20. #include <QAbstractItemModel>
  21. #include <QApplication>
  22. #include <QDesktopServices>
  23. #include <QEvent>
  24. #include <QMimeData>
  25. #include <QModelIndex>
  26. #include <QMouseEvent>
  27. #include <QTextEdit>
  28. #include <QUrl>
  29. #include <QWidget>
  30. namespace {
  31. bool canMouseInteract(const QMouseEvent &event)
  32. {
  33. return event.modifiers() & Qt::ShiftModifier;
  34. }
  35. } // namespace
  36. ItemWidget::ItemWidget(QWidget *widget)
  37. : m_widget(widget)
  38. {
  39. Q_ASSERT(widget != nullptr);
  40. // Object name for style sheet.
  41. widget->setObjectName("item");
  42. // Item widgets are not focusable.
  43. widget->setFocusPolicy(Qt::NoFocus);
  44. // Limit size of items.
  45. widget->setMaximumSize(2048, 2048);
  46. // Disable drag'n'drop by default.
  47. widget->setAcceptDrops(false);
  48. }
  49. void ItemWidget::updateSize(QSize maximumSize, int idealWidth)
  50. {
  51. QWidget *w = widget();
  52. w->setMaximumSize(maximumSize);
  53. const int idealHeight = w->heightForWidth(idealWidth);
  54. const int maximumHeight = w->heightForWidth(maximumSize.width());
  55. if (idealHeight <= 0 && maximumHeight <= 0)
  56. w->resize(w->sizeHint());
  57. else if (idealHeight != maximumHeight)
  58. w->setFixedSize( maximumSize.width(), maximumHeight );
  59. else
  60. w->setFixedSize(idealWidth, idealHeight);
  61. }
  62. void ItemWidget::setCurrent(bool current)
  63. {
  64. // Propagate mouse events to item list until the item is selected.
  65. widget()->setAttribute(Qt::WA_TransparentForMouseEvents, !current);
  66. }
  67. bool ItemWidget::filterMouseEvents(QTextEdit *edit, QEvent *event)
  68. {
  69. const auto type = event->type();
  70. bool allowMouseInteraction = true;
  71. switch (type) {
  72. case QEvent::Enter:
  73. edit->setMouseTracking(true);
  74. edit->viewport()->setCursor( QCursor() );
  75. return false;
  76. case QEvent::MouseButtonPress:
  77. case QEvent::MouseButtonDblClick: {
  78. QMouseEvent *e = static_cast<QMouseEvent*>(event);
  79. if ( !canMouseInteract(*e) )
  80. allowMouseInteraction = false;
  81. else if (e->button() == Qt::LeftButton)
  82. edit->setTextCursor( edit->cursorForPosition(e->pos()) );
  83. break;
  84. }
  85. case QEvent::MouseMove: {
  86. QMouseEvent *e = static_cast<QMouseEvent*>(event);
  87. if ( !canMouseInteract(*e) )
  88. allowMouseInteraction = false;
  89. break;
  90. }
  91. case QEvent::MouseButtonRelease: {
  92. QMouseEvent *e = static_cast<QMouseEvent*>(event);
  93. if ( canMouseInteract(*e) && edit->textCursor().hasSelection() )
  94. edit->copy();
  95. allowMouseInteraction = false;
  96. break;
  97. }
  98. default:
  99. return false;
  100. }
  101. Qt::TextInteractionFlags flags = edit->textInteractionFlags();
  102. if (allowMouseInteraction) {
  103. flags |= Qt::TextSelectableByMouse;
  104. flags |= Qt::LinksAccessibleByMouse;
  105. } else {
  106. flags &= ~Qt::TextSelectableByMouse;
  107. flags &= ~Qt::LinksAccessibleByMouse;
  108. }
  109. edit->setTextInteractionFlags(flags);
  110. if (type == QEvent::MouseButtonPress || type == QEvent::MouseMove) {
  111. const auto e = static_cast<QMouseEvent*>(event);
  112. if (allowMouseInteraction) {
  113. const auto anchor = edit->anchorAt(e->pos());
  114. if ( anchor.isEmpty() ) {
  115. edit->viewport()->setCursor( QCursor(Qt::IBeamCursor) );
  116. } else {
  117. edit->viewport()->setCursor( QCursor(Qt::PointingHandCursor) );
  118. if (type == QEvent::MouseButtonPress) {
  119. QDesktopServices::openUrl( QUrl(anchor) );
  120. e->accept();
  121. return true;
  122. }
  123. }
  124. } else {
  125. edit->viewport()->setCursor( QCursor() );
  126. }
  127. }
  128. return false;
  129. }
  130. QVariant ItemScriptable::call(const QString &method, const QVariantList &arguments)
  131. {
  132. QVariant result;
  133. QMetaObject::invokeMethod(
  134. m_scriptable, "call", Qt::DirectConnection,
  135. Q_RETURN_ARG(QVariant, result),
  136. Q_ARG(QString, method),
  137. Q_ARG(QVariantList, arguments));
  138. return result;
  139. }
  140. QVariant ItemScriptable::eval(const QString &script)
  141. {
  142. return call("eval", QVariantList() << script);
  143. }
  144. QVariantList ItemScriptable::currentArguments()
  145. {
  146. QVariantList arguments;
  147. QMetaObject::invokeMethod(
  148. m_scriptable, "currentArguments", Qt::DirectConnection,
  149. Q_RETURN_ARG(QVariantList, arguments) );
  150. return arguments;
  151. }
  152. void ItemScriptable::throwError(const QString &message)
  153. {
  154. QMetaObject::invokeMethod(
  155. m_scriptable, "throwException", Qt::DirectConnection,
  156. Q_ARG(QString, message) );
  157. }
  158. bool ItemSaverInterface::saveItems(const QString &, const QAbstractItemModel &, QIODevice *)
  159. {
  160. return false;
  161. }
  162. bool ItemSaverInterface::canRemoveItems(const QList<QModelIndex> &, QString *)
  163. {
  164. return true;
  165. }
  166. bool ItemSaverInterface::canDropItem(const QModelIndex &)
  167. {
  168. return true;
  169. }
  170. bool ItemSaverInterface::canMoveItems(const QList<QModelIndex> &)
  171. {
  172. return true;
  173. }
  174. void ItemSaverInterface::itemsRemovedByUser(const QList<QModelIndex> &)
  175. {
  176. }
  177. QVariantMap ItemSaverInterface::copyItem(const QAbstractItemModel &, const QVariantMap &itemData)
  178. {
  179. return itemData;
  180. }
  181. void ItemSaverInterface::setFocus(bool)
  182. {
  183. }
  184. ItemWidget *ItemLoaderInterface::create(const QVariantMap &, QWidget *, bool) const
  185. {
  186. return nullptr;
  187. }
  188. bool ItemLoaderInterface::canLoadItems(QIODevice *) const
  189. {
  190. return false;
  191. }
  192. bool ItemLoaderInterface::canSaveItems(const QString &) const
  193. {
  194. return false;
  195. }
  196. ItemSaverPtr ItemLoaderInterface::loadItems(const QString &, QAbstractItemModel *, QIODevice *, int)
  197. {
  198. return nullptr;
  199. }
  200. ItemSaverPtr ItemLoaderInterface::initializeTab(const QString &, QAbstractItemModel *, int)
  201. {
  202. return nullptr;
  203. }
  204. ItemWidget *ItemLoaderInterface::transform(ItemWidget *, const QVariantMap &)
  205. {
  206. return nullptr;
  207. }
  208. ItemSaverPtr ItemLoaderInterface::transformSaver(const ItemSaverPtr &saver, QAbstractItemModel *)
  209. {
  210. return saver;
  211. }
  212. bool ItemLoaderInterface::matches(const QModelIndex &, const ItemFilter &) const
  213. {
  214. return false;
  215. }
  216. QObject *ItemLoaderInterface::tests(const TestInterfacePtr &) const
  217. {
  218. return nullptr;
  219. }
  220. const QObject *ItemLoaderInterface::signaler() const
  221. {
  222. return nullptr;
  223. }
  224. ItemScriptable *ItemLoaderInterface::scriptableObject()
  225. {
  226. return nullptr;
  227. }
  228. QVector<Command> ItemLoaderInterface::commands() const
  229. {
  230. return QVector<Command>();
  231. }
  232. bool ItemLoaderInterface::data(QVariantMap *, const QModelIndex &) const
  233. {
  234. return true;
  235. }
  236. bool ItemLoaderInterface::setData(const QVariantMap &, const QModelIndex &, QAbstractItemModel *) const
  237. {
  238. return false;
  239. }
  240. QObject *ItemLoaderInterface::createExternalEditor(const QModelIndex &, const QVariantMap &, QWidget *) const
  241. {
  242. return nullptr;
  243. }