##// END OF EJS Templates
Handles tooltip for a data source item
Alexandre Leroux -
r319:4b46cbe03729
parent child
Show More
@@ -1,79 +1,82
1 1 #ifndef SCIQLOP_DATASOURCEITEM_H
2 2 #define SCIQLOP_DATASOURCEITEM_H
3 3
4 4 #include <Common/spimpl.h>
5 5
6 6 #include <QVariant>
7 7 #include <QVector>
8 8
9 9 class DataSourceItemAction;
10 10
11 11 /**
12 12 * Possible types of an item
13 13 */
14 14 enum class DataSourceItemType { NODE, PRODUCT, COMPONENT };
15 15
16 16 /**
17 17 * @brief The DataSourceItem class aims to represent a structure element of a data source.
18 18 * A data source has a tree structure that is made up of a main DataSourceItem object (root)
19 19 * containing other DataSourceItem objects (children).
20 20 * For each DataSourceItem can be associated a set of data representing it.
21 21 */
22 22 class DataSourceItem {
23 23 public:
24 24 /// Key associated with the name of the item
25 25 static const QString NAME_DATA_KEY;
26 26
27 27 explicit DataSourceItem(DataSourceItemType type, const QString &name);
28 28 explicit DataSourceItem(DataSourceItemType type, QHash<QString, QVariant> data = {});
29 29
30 30 /// @return the actions of the item as a vector
31 31 QVector<DataSourceItemAction *> actions() const noexcept;
32 32
33 33 /**
34 34 * Adds an action to the item. The item takes ownership of the action, and the action is
35 35 * automatically associated to the item
36 36 * @param action the action to add
37 37 */
38 38 void addAction(std::unique_ptr<DataSourceItemAction> action) noexcept;
39 39
40 40 /**
41 41 * Adds a child to the item. The item takes ownership of the child.
42 42 * @param child the child to add
43 43 */
44 44 void appendChild(std::unique_ptr<DataSourceItem> child) noexcept;
45 45
46 46 /**
47 47 * Returns the item's child associated to an index
48 48 * @param childIndex the index to search
49 49 * @return a pointer to the child if index is valid, nullptr otherwise
50 50 */
51 51 DataSourceItem *child(int childIndex) const noexcept;
52 52
53 53 int childCount() const noexcept;
54 54
55 55 /**
56 56 * Get the data associated to a key
57 57 * @param key the key to search
58 58 * @return the data found if key is valid, default QVariant otherwise
59 59 */
60 60 QVariant data(const QString &key) const noexcept;
61 61
62 /// Gets all data
63 const QHash<QString, QVariant> &data() const noexcept;
64
62 65 bool isRoot() const noexcept;
63 66
64 67 QString name() const noexcept;
65 68
66 69 /**
67 70 * Get the item's parent
68 71 * @return a pointer to the parent if it exists, nullptr if the item is a root
69 72 */
70 73 DataSourceItem *parentItem() const noexcept;
71 74
72 75 DataSourceItemType type() const noexcept;
73 76
74 77 private:
75 78 class DataSourceItemPrivate;
76 79 spimpl::unique_impl_ptr<DataSourceItemPrivate> impl;
77 80 };
78 81
79 82 #endif // SCIQLOP_DATASOURCEITEMMODEL_H
@@ -1,91 +1,96
1 1 #include <DataSource/DataSourceItem.h>
2 2 #include <DataSource/DataSourceItemAction.h>
3 3
4 4 #include <QVector>
5 5
6 6 const QString DataSourceItem::NAME_DATA_KEY = QStringLiteral("name");
7 7
8 8 struct DataSourceItem::DataSourceItemPrivate {
9 9 explicit DataSourceItemPrivate(DataSourceItemType type, QHash<QString, QVariant> data)
10 10 : m_Parent{nullptr}, m_Children{}, m_Type{type}, m_Data{std::move(data)}, m_Actions{}
11 11 {
12 12 }
13 13
14 14 DataSourceItem *m_Parent;
15 15 std::vector<std::unique_ptr<DataSourceItem> > m_Children;
16 16 DataSourceItemType m_Type;
17 17 QHash<QString, QVariant> m_Data;
18 18 std::vector<std::unique_ptr<DataSourceItemAction> > m_Actions;
19 19 };
20 20
21 21 DataSourceItem::DataSourceItem(DataSourceItemType type, const QString &name)
22 22 : DataSourceItem{type, QHash<QString, QVariant>{{NAME_DATA_KEY, name}}}
23 23 {
24 24 }
25 25
26 26 DataSourceItem::DataSourceItem(DataSourceItemType type, QHash<QString, QVariant> data)
27 27 : impl{spimpl::make_unique_impl<DataSourceItemPrivate>(type, std::move(data))}
28 28 {
29 29 }
30 30
31 31 QVector<DataSourceItemAction *> DataSourceItem::actions() const noexcept
32 32 {
33 33 auto result = QVector<DataSourceItemAction *>{};
34 34
35 35 std::transform(std::cbegin(impl->m_Actions), std::cend(impl->m_Actions),
36 36 std::back_inserter(result), [](const auto &action) { return action.get(); });
37 37
38 38 return result;
39 39 }
40 40
41 41 void DataSourceItem::addAction(std::unique_ptr<DataSourceItemAction> action) noexcept
42 42 {
43 43 action->setDataSourceItem(this);
44 44 impl->m_Actions.push_back(std::move(action));
45 45 }
46 46
47 47 void DataSourceItem::appendChild(std::unique_ptr<DataSourceItem> child) noexcept
48 48 {
49 49 child->impl->m_Parent = this;
50 50 impl->m_Children.push_back(std::move(child));
51 51 }
52 52
53 53 DataSourceItem *DataSourceItem::child(int childIndex) const noexcept
54 54 {
55 55 if (childIndex < 0 || childIndex >= childCount()) {
56 56 return nullptr;
57 57 }
58 58 else {
59 59 return impl->m_Children.at(childIndex).get();
60 60 }
61 61 }
62 62
63 63 int DataSourceItem::childCount() const noexcept
64 64 {
65 65 return impl->m_Children.size();
66 66 }
67 67
68 68 QVariant DataSourceItem::data(const QString &key) const noexcept
69 69 {
70 70 return impl->m_Data.value(key);
71 71 }
72 72
73 const QHash<QString, QVariant> &DataSourceItem::data() const noexcept
74 {
75 return impl->m_Data;
76 }
77
73 78 bool DataSourceItem::isRoot() const noexcept
74 79 {
75 80 return impl->m_Parent == nullptr;
76 81 }
77 82
78 83 QString DataSourceItem::name() const noexcept
79 84 {
80 85 return data(NAME_DATA_KEY).toString();
81 86 }
82 87
83 88 DataSourceItem *DataSourceItem::parentItem() const noexcept
84 89 {
85 90 return impl->m_Parent;
86 91 }
87 92
88 93 DataSourceItemType DataSourceItem::type() const noexcept
89 94 {
90 95 return impl->m_Type;
91 96 }
@@ -1,122 +1,171
1 1 #include <DataSource/DataSourceItem.h>
2 2 #include <DataSource/DataSourceItemAction.h>
3 3 #include <DataSource/DataSourceTreeWidgetItem.h>
4 4
5 5 #include <QAction>
6 6
7 7 Q_LOGGING_CATEGORY(LOG_DataSourceTreeWidgetItem, "DataSourceTreeWidgetItem")
8 8
9 9 namespace {
10 10
11 11 // Column indexes
12 12 const auto NAME_COLUMN = 0;
13 13
14 14 QIcon itemIcon(const DataSourceItem *dataSource)
15 15 {
16 16 if (dataSource) {
17 17 auto dataSourceType = dataSource->type();
18 18 switch (dataSourceType) {
19 19 case DataSourceItemType::NODE: {
20 20 return dataSource->isRoot() ? QIcon{":/icones/dataSourceRoot.png"}
21 21 : QIcon{":/icones/dataSourceNode.png"};
22 22 }
23 23 case DataSourceItemType::PRODUCT:
24 24 return QIcon{":/icones/dataSourceProduct.png"};
25 25 case DataSourceItemType::COMPONENT:
26 26 return QIcon{":/icones/dataSourceComponent.png"};
27 27 default:
28 28 // No action
29 29 break;
30 30 }
31 31
32 32 qCWarning(LOG_DataSourceTreeWidgetItem())
33 33 << QObject::tr("Can't set data source icon : unknown data source type");
34 34 }
35 35 else {
36 36 qCCritical(LOG_DataSourceTreeWidgetItem())
37 37 << QObject::tr("Can't set data source icon : the data source is null");
38 38 }
39 39
40 40 // Default cases
41 41 return QIcon{};
42 42 }
43 43
44 /// @return the tooltip text for a variant. The text depends on whether the data is a simple variant
45 /// or a list of variants
46 QString tooltipValue(const QVariant &variant) noexcept
47 {
48 // If the variant is a list of variants, the text of the tooltip is of the form: {val1, val2,
49 // ...}
50 if (variant.canConvert<QVariantList>()) {
51 auto valueString = QStringLiteral("{");
52
53 auto variantList = variant.value<QVariantList>();
54 for (auto it = variantList.cbegin(), end = variantList.cend(); it != end; ++it) {
55 valueString.append(it->toString());
56
57 if (std::distance(it, end) != 1) {
58 valueString.append(", ");
59 }
60 }
61
62 valueString.append(QStringLiteral("}"));
63
64 return valueString;
65 }
66 else {
67 return variant.toString();
68 }
69 }
70
71 QString itemTooltip(const DataSourceItem *dataSource) noexcept
72 {
73 // The tooltip displays all item's data
74 if (dataSource) {
75 auto result = QString{};
76
77 const auto &data = dataSource->data();
78 for (auto it = data.cbegin(), end = data.cend(); it != end; ++it) {
79 result.append(QString{"<b>%1:</b> %2<br/>"}.arg(it.key(), tooltipValue(it.value())));
80 }
81
82 return result;
83 }
84 else {
85 qCCritical(LOG_DataSourceTreeWidgetItem())
86 << QObject::tr("Can't set data source tooltip : the data source is null");
87
88 return QString{};
89 }
90 }
91
44 92 } // namespace
45 93
46 94 struct DataSourceTreeWidgetItem::DataSourceTreeWidgetItemPrivate {
47 95 explicit DataSourceTreeWidgetItemPrivate(const DataSourceItem *data) : m_Data{data} {}
48 96
49 97 /// Model used to retrieve data source information
50 98 const DataSourceItem *m_Data;
51 99 /// Actions associated to the item. The parent of the item (QTreeWidget) takes the ownership of
52 100 /// the actions
53 101 QList<QAction *> m_Actions;
54 102 };
55 103
56 104 DataSourceTreeWidgetItem::DataSourceTreeWidgetItem(const DataSourceItem *data, int type)
57 105 : DataSourceTreeWidgetItem{nullptr, data, type}
58 106 {
59 107 }
60 108
61 109 DataSourceTreeWidgetItem::DataSourceTreeWidgetItem(QTreeWidget *parent, const DataSourceItem *data,
62 110 int type)
63 111 : QTreeWidgetItem{parent, type},
64 112 impl{spimpl::make_unique_impl<DataSourceTreeWidgetItemPrivate>(data)}
65 113 {
66 // Sets the icon depending on the data source
114 // Sets the icon and the tooltip depending on the data source
67 115 setIcon(0, itemIcon(impl->m_Data));
116 setToolTip(0, itemTooltip(impl->m_Data));
68 117
69 118 // Generates tree actions based on the item actions
70 119 auto createTreeAction = [this, &parent](const auto &itemAction) {
71 120 auto treeAction = new QAction{itemAction->name(), parent};
72 121
73 122 // Executes item action when tree action is triggered
74 123 QObject::connect(treeAction, &QAction::triggered, itemAction,
75 124 &DataSourceItemAction::execute);
76 125
77 126 return treeAction;
78 127 };
79 128
80 129 auto itemActions = impl->m_Data->actions();
81 130 std::transform(std::cbegin(itemActions), std::cend(itemActions),
82 131 std::back_inserter(impl->m_Actions), createTreeAction);
83 132 }
84 133
85 134 QVariant DataSourceTreeWidgetItem::data(int column, int role) const
86 135 {
87 136 if (role == Qt::DisplayRole) {
88 137 if (impl->m_Data) {
89 138 switch (column) {
90 139 case NAME_COLUMN:
91 140 return impl->m_Data->name();
92 141 default:
93 142 // No action
94 143 break;
95 144 }
96 145
97 146 qCWarning(LOG_DataSourceTreeWidgetItem())
98 147 << QObject::tr("Can't get data (unknown column %1)").arg(column);
99 148 }
100 149 else {
101 150 qCCritical(LOG_DataSourceTreeWidgetItem()) << QObject::tr("Can't get data (null item)");
102 151 }
103 152
104 153 return QVariant{};
105 154 }
106 155 else {
107 156 return QTreeWidgetItem::data(column, role);
108 157 }
109 158 }
110 159
111 160 void DataSourceTreeWidgetItem::setData(int column, int role, const QVariant &value)
112 161 {
113 162 // Data can't be changed by edition
114 163 if (role != Qt::EditRole) {
115 164 QTreeWidgetItem::setData(column, role, value);
116 165 }
117 166 }
118 167
119 168 QList<QAction *> DataSourceTreeWidgetItem::actions() const noexcept
120 169 {
121 170 return impl->m_Actions;
122 171 }
General Comments 0
You need to be logged in to leave comments. Login now