40
40
#include <lib/semanticinfo/tagitemdelegate.h>
41
41
#include <lib/semanticinfo/tagmodel.h>
46
class TagCompleterModel : public QSortFilterProxyModel {
46
class TagCompleterModel : public QSortFilterProxyModel
48
TagCompleterModel(QObject* parent)
49
: QSortFilterProxyModel(parent)
54
void setTagInfo(const TagInfo& tagInfo) {
55
mExcludedTagSet.clear();
56
TagInfo::ConstIterator
59
for(; it!=end; ++it) {
61
mExcludedTagSet << it.key();
68
void setSemanticInfoBackEnd(AbstractSemanticInfoBackEnd* backEnd) {
69
setSourceModel(TagModel::createAllTagsModel(this, backEnd));
49
TagCompleterModel(QObject* parent)
50
: QSortFilterProxyModel(parent) {
53
void setTagInfo(const TagInfo& tagInfo)
55
mExcludedTagSet.clear();
56
TagInfo::ConstIterator
59
for (; it != end; ++it) {
61
mExcludedTagSet << it.key();
67
void setSemanticInfoBackEnd(AbstractSemanticInfoBackEnd* backEnd)
69
setSourceModel(TagModel::createAllTagsModel(this, backEnd));
74
virtual bool filterAcceptsRow(int sourceRow, const QModelIndex& sourceParent) const {
75
QModelIndex sourceIndex = sourceModel()->index(sourceRow, 0, sourceParent);
76
SemanticInfoTag tag = sourceIndex.data(TagModel::TagRole).toString();
77
return !mExcludedTagSet.contains(tag);
73
virtual bool filterAcceptsRow(int sourceRow, const QModelIndex& sourceParent) const {
74
QModelIndex sourceIndex = sourceModel()->index(sourceRow, 0, sourceParent);
75
SemanticInfoTag tag = sourceIndex.data(TagModel::TagRole).toString();
76
return !mExcludedTagSet.contains(tag);
82
TagSet mExcludedTagSet;
80
TagSet mExcludedTagSet;
87
84
* A simple class to eat return keys. We use it to avoid propagating the return
88
85
* key from our KLineEdit to a dialog using TagWidget.
89
86
* We can't use KLineEdit::setTrapReturnKey() because it does not play well
90
87
* with QCompleter, it only deals with KCompletion.
92
class ReturnKeyEater : public QObject {
89
class ReturnKeyEater : public QObject
94
ReturnKeyEater(QObject* parent = 0)
92
ReturnKeyEater(QObject* parent = 0)
99
virtual bool eventFilter(QObject*, QEvent* event) {
100
if (event->type() == QEvent::KeyPress || event->type() == QEvent::KeyRelease) {
101
QKeyEvent* keyEvent = static_cast<QKeyEvent*>(event);
102
switch (keyEvent->key()) {
97
virtual bool eventFilter(QObject*, QEvent* event) {
98
if (event->type() == QEvent::KeyPress || event->type() == QEvent::KeyRelease) {
99
QKeyEvent* keyEvent = static_cast<QKeyEvent*>(event);
100
switch (keyEvent->key()) {
114
112
struct TagWidgetPrivate {
117
QListView* mListView;
118
QComboBox* mComboBox;
119
KPushButton* mAddButton;
120
AbstractSemanticInfoBackEnd* mBackEnd;
121
TagCompleterModel* mTagCompleterModel;
122
TagModel* mAssignedTagModel;
125
void setupWidgets() {
126
mListView = new QListView;
127
TagItemDelegate* delegate = new TagItemDelegate(mListView);
128
QObject::connect(delegate, SIGNAL(removeTagRequested(const SemanticInfoTag&)),
129
that, SLOT(removeTag(const SemanticInfoTag&)));
130
QObject::connect(delegate, SIGNAL(assignTagToAllRequested(const SemanticInfoTag&)),
131
that, SLOT(assignTag(const SemanticInfoTag&)));
132
mListView->setItemDelegate(delegate);
133
mListView->setModel(mAssignedTagModel);
135
mComboBox = new QComboBox;
136
mComboBox->setEditable(true);
137
mComboBox->setInsertPolicy(QComboBox::NoInsert);
139
mTagCompleterModel = new TagCompleterModel(that);
140
QCompleter* completer = new QCompleter(that);
141
completer->setCaseSensitivity(Qt::CaseInsensitive);
142
completer->setModel(mTagCompleterModel);
143
mComboBox->setCompleter(completer);
145
mComboBox->setModel(mTagCompleterModel);
147
mAddButton = new KPushButton;
148
mAddButton->setIcon(KIcon("list-add"));
149
mAddButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
150
QObject::connect(mAddButton, SIGNAL(clicked()),
151
that, SLOT(addTagFromComboBox()));
153
QVBoxLayout* layout = new QVBoxLayout(that);
154
layout->setMargin(0);
155
layout->addWidget(mListView);
157
QHBoxLayout* hLayout = new QHBoxLayout;
158
hLayout->addWidget(mComboBox);
159
hLayout->addWidget(mAddButton);
160
layout->addLayout(hLayout);
162
that->setTabOrder(mComboBox, mListView);
166
void fillTagModel() {
169
mAssignedTagModel->clear();
170
TagInfo::ConstIterator
171
it = mTagInfo.constBegin(),
172
end = mTagInfo.constEnd();
173
for(; it!=end; ++it) {
174
mAssignedTagModel->addTag(
177
it.value() ? TagModel::FullyAssigned : TagModel::PartiallyAssigned);
182
void updateCompleterModel() {
183
mTagCompleterModel->setTagInfo(mTagInfo);
115
QListView* mListView;
116
QComboBox* mComboBox;
117
KPushButton* mAddButton;
118
AbstractSemanticInfoBackEnd* mBackEnd;
119
TagCompleterModel* mTagCompleterModel;
120
TagModel* mAssignedTagModel;
124
mListView = new QListView;
125
TagItemDelegate* delegate = new TagItemDelegate(mListView);
126
QObject::connect(delegate, SIGNAL(removeTagRequested(SemanticInfoTag)),
127
q, SLOT(removeTag(SemanticInfoTag)));
128
QObject::connect(delegate, SIGNAL(assignTagToAllRequested(SemanticInfoTag)),
129
q, SLOT(assignTag(SemanticInfoTag)));
130
mListView->setItemDelegate(delegate);
131
mListView->setModel(mAssignedTagModel);
133
mComboBox = new QComboBox;
134
mComboBox->setEditable(true);
135
mComboBox->setInsertPolicy(QComboBox::NoInsert);
137
mTagCompleterModel = new TagCompleterModel(q);
138
QCompleter* completer = new QCompleter(q);
139
completer->setCaseSensitivity(Qt::CaseInsensitive);
140
completer->setModel(mTagCompleterModel);
141
mComboBox->setCompleter(completer);
143
mComboBox->setModel(mTagCompleterModel);
145
mAddButton = new KPushButton;
146
mAddButton->setIcon(KIcon("list-add"));
147
mAddButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
148
QObject::connect(mAddButton, SIGNAL(clicked()),
149
q, SLOT(addTagFromComboBox()));
151
QVBoxLayout* layout = new QVBoxLayout(q);
152
layout->setMargin(0);
153
layout->addWidget(mListView);
155
QHBoxLayout* hLayout = new QHBoxLayout;
156
hLayout->addWidget(mComboBox);
157
hLayout->addWidget(mAddButton);
158
layout->addLayout(hLayout);
160
q->setTabOrder(mComboBox, mListView);
167
mAssignedTagModel->clear();
168
TagInfo::ConstIterator
169
it = mTagInfo.constBegin(),
170
end = mTagInfo.constEnd();
171
for (; it != end; ++it) {
172
mAssignedTagModel->addTag(
175
it.value() ? TagModel::FullyAssigned : TagModel::PartiallyAssigned);
179
void updateCompleterModel()
181
mTagCompleterModel->setTagInfo(mTagInfo);
188
185
TagWidget::TagWidget(QWidget* parent)
189
186
: QWidget(parent)
190
, d(new TagWidgetPrivate) {
193
d->mAssignedTagModel = new TagModel(this);
195
installEventFilter(new ReturnKeyEater(this));
197
connect(d->mComboBox->lineEdit(), SIGNAL(returnPressed()),
198
SLOT(addTagFromComboBox()) );
202
TagWidget::~TagWidget() {
207
void TagWidget::setSemanticInfoBackEnd(AbstractSemanticInfoBackEnd* backEnd) {
208
d->mBackEnd = backEnd;
209
d->mAssignedTagModel->setSemanticInfoBackEnd(backEnd);
210
d->mTagCompleterModel->setSemanticInfoBackEnd(backEnd);
214
void TagWidget::setTagInfo(const TagInfo& tagInfo) {
215
d->mTagInfo = tagInfo;
217
d->updateCompleterModel();
221
void TagWidget::addTagFromComboBox() {
222
Q_ASSERT(d->mBackEnd);
223
QString label = d->mComboBox->currentText();
224
if (label.isEmpty()) {
227
assignTag(d->mBackEnd->tagForLabel(label.trimmed()));
229
// Use a QTimer because if the tag is new, it will be inserted in the model
230
// and QComboBox will sometimes select it. At least it does so when the
232
QTimer::singleShot(0, d->mComboBox, SLOT(clearEditText()));
236
void TagWidget::assignTag(const SemanticInfoTag& tag) {
237
d->mTagInfo[tag] = true;
238
d->mAssignedTagModel->addTag(tag);
239
d->updateCompleterModel();
241
emit tagAssigned(tag);
245
void TagWidget::removeTag(const SemanticInfoTag& tag) {
246
d->mTagInfo.remove(tag);
247
d->mAssignedTagModel->removeTag(tag);
248
d->updateCompleterModel();
250
emit tagRemoved(tag);
187
, d(new TagWidgetPrivate)
191
d->mAssignedTagModel = new TagModel(this);
193
installEventFilter(new ReturnKeyEater(this));
195
connect(d->mComboBox->lineEdit(), SIGNAL(returnPressed()),
196
SLOT(addTagFromComboBox()));
199
TagWidget::~TagWidget()
204
void TagWidget::setSemanticInfoBackEnd(AbstractSemanticInfoBackEnd* backEnd)
206
d->mBackEnd = backEnd;
207
d->mAssignedTagModel->setSemanticInfoBackEnd(backEnd);
208
d->mTagCompleterModel->setSemanticInfoBackEnd(backEnd);
211
void TagWidget::setTagInfo(const TagInfo& tagInfo)
213
d->mTagInfo = tagInfo;
215
d->updateCompleterModel();
218
void TagWidget::addTagFromComboBox()
220
Q_ASSERT(d->mBackEnd);
221
QString label = d->mComboBox->currentText();
222
if (label.isEmpty()) {
225
assignTag(d->mBackEnd->tagForLabel(label.trimmed()));
227
// Use a QTimer because if the tag is new, it will be inserted in the model
228
// and QComboBox will sometimes select it. At least it does so when the
230
QTimer::singleShot(0, d->mComboBox, SLOT(clearEditText()));
233
void TagWidget::assignTag(const SemanticInfoTag& tag)
235
d->mTagInfo[tag] = true;
236
d->mAssignedTagModel->addTag(tag);
237
d->updateCompleterModel();
239
emit tagAssigned(tag);
242
void TagWidget::removeTag(const SemanticInfoTag& tag)
244
d->mTagInfo.remove(tag);
245
d->mAssignedTagModel->removeTag(tag);
246
d->updateCompleterModel();
248
emit tagRemoved(tag);