ClipboardHistoryModel.cpp 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. /*
  2. * Copyright (c) 2019-2020, Sergey Bugaev <bugaevc@serenityos.org>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include "ClipboardHistoryModel.h"
  7. #include <AK/NumberFormat.h>
  8. #include <AK/StringBuilder.h>
  9. NonnullRefPtr<ClipboardHistoryModel> ClipboardHistoryModel::create()
  10. {
  11. return adopt_ref(*new ClipboardHistoryModel());
  12. }
  13. ClipboardHistoryModel::~ClipboardHistoryModel()
  14. {
  15. }
  16. String ClipboardHistoryModel::column_name(int column) const
  17. {
  18. switch (column) {
  19. case Column::Data:
  20. return "Data";
  21. case Column::Type:
  22. return "Type";
  23. case Column::Size:
  24. return "Size";
  25. default:
  26. VERIFY_NOT_REACHED();
  27. }
  28. }
  29. static const char* bpp_for_format_resilient(String format)
  30. {
  31. unsigned format_uint = format.to_uint().value_or(static_cast<unsigned>(Gfx::BitmapFormat::Invalid));
  32. // Cannot use Gfx::Bitmap::bpp_for_format here, as we have to accept invalid enum values.
  33. switch (static_cast<Gfx::BitmapFormat>(format_uint)) {
  34. case Gfx::BitmapFormat::Indexed1:
  35. return "1";
  36. case Gfx::BitmapFormat::Indexed2:
  37. return "2";
  38. case Gfx::BitmapFormat::Indexed4:
  39. return "4";
  40. case Gfx::BitmapFormat::Indexed8:
  41. return "8";
  42. case Gfx::BitmapFormat::BGRx8888:
  43. case Gfx::BitmapFormat::BGRA8888:
  44. return "32";
  45. case Gfx::BitmapFormat::Invalid:
  46. /* fall-through */
  47. default:
  48. return "?";
  49. }
  50. }
  51. GUI::Variant ClipboardHistoryModel::data(const GUI::ModelIndex& index, GUI::ModelRole role) const
  52. {
  53. if (role != GUI::ModelRole::Display)
  54. return {};
  55. auto& data_and_type = m_history_items[index.row()];
  56. switch (index.column()) {
  57. case Column::Data:
  58. if (data_and_type.mime_type.starts_with("text/"))
  59. return String::copy(data_and_type.data);
  60. if (data_and_type.mime_type == "image/x-serenityos") {
  61. StringBuilder builder;
  62. builder.append("[");
  63. builder.append(data_and_type.metadata.get("width").value_or("?"));
  64. builder.append('x');
  65. builder.append(data_and_type.metadata.get("height").value_or("?"));
  66. builder.append('x');
  67. builder.append(bpp_for_format_resilient(data_and_type.metadata.get("height").value_or("0")));
  68. builder.append(" bitmap");
  69. builder.append("]");
  70. return builder.to_string();
  71. }
  72. if (data_and_type.mime_type.starts_with("glyph/")) {
  73. StringBuilder builder;
  74. builder.append("[");
  75. builder.append(data_and_type.metadata.get("width").value_or("?"));
  76. builder.append("x");
  77. builder.append(data_and_type.metadata.get("height").value_or("?"));
  78. builder.append("] ");
  79. builder.append("(");
  80. builder.append(data_and_type.metadata.get("char").value_or(""));
  81. builder.append(")");
  82. return builder.to_string();
  83. }
  84. return "<...>";
  85. case Column::Type:
  86. return data_and_type.mime_type;
  87. case Column::Size:
  88. return AK::human_readable_size(data_and_type.data.size());
  89. default:
  90. VERIFY_NOT_REACHED();
  91. }
  92. }
  93. void ClipboardHistoryModel::add_item(const GUI::Clipboard::DataAndType& item)
  94. {
  95. m_history_items.remove_first_matching([&](GUI::Clipboard::DataAndType& existing) {
  96. return existing.data == item.data && existing.mime_type == item.mime_type;
  97. });
  98. if (m_history_items.size() == m_history_limit)
  99. m_history_items.take_last();
  100. m_history_items.prepend(item);
  101. invalidate();
  102. }
  103. void ClipboardHistoryModel::remove_item(int index)
  104. {
  105. m_history_items.remove(index);
  106. }