54
54
#include <lib/semanticinfo/semanticinfodirmodel.h>
55
55
#include <lib/semanticinfo/sorteddirmodel.h>
59
60
static const int RATING_INDICATOR_HIDE_DELAY = 3000;
62
62
struct SemanticInfoDialog : public KDialog, public Ui_SemanticInfoDialog {
63
SemanticInfoDialog(QWidget* parent)
66
QWidget* mainWidget = new QWidget;
67
setMainWidget(mainWidget);
69
mainWidget->layout()->setMargin(0);
70
setWindowTitle(mainWidget->windowTitle());
72
restoreDialogSize(configGroup());
75
~SemanticInfoDialog() {
76
KConfigGroup group = configGroup();
77
saveDialogSize(group);
80
KConfigGroup configGroup() const {
81
KSharedConfigPtr config = KGlobal::config();
82
return KConfigGroup(config, "SemanticInfoDialog");
63
SemanticInfoDialog(QWidget* parent)
66
QWidget* mainWidget = new QWidget;
67
setMainWidget(mainWidget);
69
mainWidget->layout()->setMargin(0);
70
setWindowTitle(mainWidget->windowTitle());
72
restoreDialogSize(configGroup());
75
~SemanticInfoDialog() {
76
KConfigGroup group = configGroup();
77
saveDialogSize(group);
80
KConfigGroup configGroup() const {
81
KSharedConfigPtr config = KGlobal::config();
82
return KConfigGroup(config, "SemanticInfoDialog");
87
class RatingIndicator : public HudWidget {
86
class RatingIndicator : public HudWidget
89
RatingIndicator(QWidget* parent)
91
, mRatingWidget(new KRatingWidget)
92
, mHideTimer(new QTimer(this))
94
init(mRatingWidget, OptionNone);
95
WidgetFloater* floater = new WidgetFloater(parent);
96
floater->setAlignment(Qt::AlignHCenter | Qt::AlignBottom);
97
floater->setVerticalMargin(
99
+ parent->style()->pixelMetric(QStyle::PM_ScrollBarExtent)
101
floater->setChildWidget(this);
103
mHideTimer->setInterval(RATING_INDICATOR_HIDE_DELAY);
104
mHideTimer->setSingleShot(true);
105
connect(mHideTimer, SIGNAL(timeout()), SLOT(deleteLater()));
109
void setRating(int rating) {
110
mRatingWidget->setRating(rating);
89
RatingIndicator(QWidget* parent)
91
, mRatingWidget(new KRatingWidget)
92
, mHideTimer(new QTimer(this)) {
93
init(mRatingWidget, OptionNone);
94
WidgetFloater* floater = new WidgetFloater(parent);
95
floater->setAlignment(Qt::AlignHCenter | Qt::AlignBottom);
96
floater->setVerticalMargin(
98
+ parent->style()->pixelMetric(QStyle::PM_ScrollBarExtent)
100
floater->setChildWidget(this);
102
mHideTimer->setInterval(RATING_INDICATOR_HIDE_DELAY);
103
mHideTimer->setSingleShot(true);
104
connect(mHideTimer, SIGNAL(timeout()), SLOT(deleteLater()));
108
void setRating(int rating)
110
mRatingWidget->setRating(rating);
120
KRatingWidget* mRatingWidget;
121
KRatingWidget* mRatingWidget;
125
125
struct SemanticInfoContextManagerItemPrivate : public Ui_SemanticInfoSideBarItem {
126
SemanticInfoContextManagerItem* that;
127
SideBarGroup* mGroup;
128
KActionCollection* mActionCollection;
129
DocumentPanel* mDocumentPanel;
130
QPointer<SemanticInfoDialog> mSemanticInfoDialog;
132
KAction* mEditTagsAction;
133
QSignalMapper* mRatingMapper;
134
/** A list of all actions, so that we can disable them when necessary */
135
QList<KAction*> mActions;
136
QPointer<RatingIndicator> mRatingIndicator;
139
mGroup = new SideBarGroup(i18n("Semantic Information"));
140
that->setWidget(mGroup);
141
EventWatcher::install(mGroup, QEvent::Show, that, SLOT(update()));
143
QWidget* container = new QWidget;
145
container->layout()->setMargin(0);
146
mGroup->addWidget(container);
148
QObject::connect(mRatingWidget, SIGNAL(ratingChanged(int)),
149
that, SLOT(slotRatingChanged(int)));
150
QObject::connect(mRatingMapper, SIGNAL(mapped(int)),
151
mRatingWidget, SLOT(setRating(int)) );
153
mDescriptionTextEdit->installEventFilter(that);
155
QObject::connect(mTagLabel, SIGNAL(linkActivated(const QString&)),
156
mEditTagsAction, SLOT(trigger()) );
160
void setupActions() {
161
KActionCategory* edit = new KActionCategory(i18nc("@title actions category","Edit"), mActionCollection);
163
mEditTagsAction = edit->addAction("edit_tags");
164
mEditTagsAction->setText(i18nc("@action", "Edit Tags"));
165
mEditTagsAction->setShortcut(Qt::CTRL | Qt::Key_T);
166
QObject::connect(mEditTagsAction, SIGNAL(triggered()),
167
that, SLOT(showSemanticInfoDialog()) );
168
mActions << mEditTagsAction;
170
mRatingMapper = new QSignalMapper(that);
171
for (int rating=0; rating <= 5; ++rating) {
172
KAction* action = edit->addAction(QString("rate_%1").arg(rating));
174
action->setText(i18nc("@action Rating value of zero", "Zero"));
176
action->setText(QString(rating, QChar(0x22C6))); /* 0x22C6 is the 'star' character */
178
action->setShortcut(Qt::Key_0 + rating);
179
QObject::connect(action, SIGNAL(triggered()), mRatingMapper, SLOT(map()) );
180
mRatingMapper->setMapping(action, rating * 2);
183
QObject::connect(mRatingMapper, SIGNAL(mapped(int)), that, SLOT(slotRatingChanged(int)) );
187
void updateTagLabel() {
188
if (that->contextManager()->selectedFileItemList().isEmpty()) {
193
AbstractSemanticInfoBackEnd* backEnd = that->contextManager()->dirModel()->semanticInfoBackEnd();
195
TagInfo::ConstIterator
196
it = mTagInfo.constBegin(),
197
end = mTagInfo.constEnd();
198
QMap<QString, QString> labelMap;
199
for (; it!=end; ++it) {
200
SemanticInfoTag tag = it.key();
201
QString label = backEnd->labelForTag(tag);
203
// Tag is not present for all urls
206
labelMap[label.toLower()] = label;
208
QStringList labels(labelMap.values());
210
QString editLink = i18n("Edit");
211
QString text = labels.join(", ") + QString(" <a href='edit'>%1</a>").arg(editLink);
212
mTagLabel->setText(text);
216
void updateSemanticInfoDialog() {
217
mSemanticInfoDialog->mTagWidget->setEnabled(!that->contextManager()->selectedFileItemList().isEmpty());
218
mSemanticInfoDialog->mTagWidget->setTagInfo(mTagInfo);
126
SemanticInfoContextManagerItem* q;
127
SideBarGroup* mGroup;
128
KActionCollection* mActionCollection;
129
ViewMainPage* mViewMainPage;
130
QPointer<SemanticInfoDialog> mSemanticInfoDialog;
132
KAction* mEditTagsAction;
133
QSignalMapper* mRatingMapper;
134
/** A list of all actions, so that we can disable them when necessary */
135
QList<KAction*> mActions;
136
QPointer<RatingIndicator> mRatingIndicator;
140
mGroup = new SideBarGroup(i18n("Semantic Information"));
141
q->setWidget(mGroup);
142
EventWatcher::install(mGroup, QEvent::Show, q, SLOT(update()));
144
QWidget* container = new QWidget;
146
container->layout()->setMargin(0);
147
mGroup->addWidget(container);
149
QObject::connect(mRatingWidget, SIGNAL(ratingChanged(int)),
150
q, SLOT(slotRatingChanged(int)));
151
QObject::connect(mRatingMapper, SIGNAL(mapped(int)),
152
mRatingWidget, SLOT(setRating(int)));
154
mDescriptionTextEdit->installEventFilter(q);
156
QObject::connect(mTagLabel, SIGNAL(linkActivated(QString)),
157
mEditTagsAction, SLOT(trigger()));
162
KActionCategory* edit = new KActionCategory(i18nc("@title actions category", "Edit"), mActionCollection);
164
mEditTagsAction = edit->addAction("edit_tags");
165
mEditTagsAction->setText(i18nc("@action", "Edit Tags"));
166
mEditTagsAction->setShortcut(Qt::CTRL | Qt::Key_T);
167
QObject::connect(mEditTagsAction, SIGNAL(triggered()),
168
q, SLOT(showSemanticInfoDialog()));
169
mActions << mEditTagsAction;
171
mRatingMapper = new QSignalMapper(q);
172
for (int rating = 0; rating <= 5; ++rating) {
173
KAction* action = edit->addAction(QString("rate_%1").arg(rating));
175
action->setText(i18nc("@action Rating value of zero", "Zero"));
177
action->setText(QString(rating, QChar(0x22C6))); /* 0x22C6 is the 'star' character */
179
action->setShortcut(Qt::Key_0 + rating);
180
QObject::connect(action, SIGNAL(triggered()), mRatingMapper, SLOT(map()));
181
mRatingMapper->setMapping(action, rating * 2);
184
QObject::connect(mRatingMapper, SIGNAL(mapped(int)), q, SLOT(slotRatingChanged(int)));
187
void updateTagLabel()
189
if (q->contextManager()->selectedFileItemList().isEmpty()) {
194
AbstractSemanticInfoBackEnd* backEnd = q->contextManager()->dirModel()->semanticInfoBackEnd();
196
TagInfo::ConstIterator
197
it = mTagInfo.constBegin(),
198
end = mTagInfo.constEnd();
199
QMap<QString, QString> labelMap;
200
for (; it != end; ++it) {
201
SemanticInfoTag tag = it.key();
202
QString label = backEnd->labelForTag(tag);
204
// Tag is not present for all urls
207
labelMap[label.toLower()] = label;
209
QStringList labels(labelMap.values());
211
QString editLink = i18n("Edit");
212
QString text = labels.join(", ") + QString(" <a href='edit'>%1</a>").arg(editLink);
213
mTagLabel->setText(text);
216
void updateSemanticInfoDialog()
218
mSemanticInfoDialog->mTagWidget->setEnabled(!q->contextManager()->selectedFileItemList().isEmpty());
219
mSemanticInfoDialog->mTagWidget->setTagInfo(mTagInfo);
223
SemanticInfoContextManagerItem::SemanticInfoContextManagerItem(ContextManager* manager, KActionCollection* actionCollection, DocumentPanel* documentPanel)
223
SemanticInfoContextManagerItem::SemanticInfoContextManagerItem(ContextManager* manager, KActionCollection* actionCollection, ViewMainPage* documentPanel)
224
224
: AbstractContextManagerItem(manager)
225
, d(new SemanticInfoContextManagerItemPrivate) {
227
d->mActionCollection = actionCollection;
228
d->mDocumentPanel = documentPanel;
230
connect(contextManager(), SIGNAL(selectionChanged()),
231
SLOT(slotSelectionChanged()) );
232
connect(contextManager(), SIGNAL(selectionDataChanged()),
234
connect(contextManager(), SIGNAL(currentDirUrlChanged()),
242
SemanticInfoContextManagerItem::~SemanticInfoContextManagerItem() {
247
inline int ratingForVariant(const QVariant& variant) {
248
if (variant.isValid()) {
249
return variant.toInt();
256
void SemanticInfoContextManagerItem::slotSelectionChanged() {
257
if (d->mRatingIndicator) {
258
d->mRatingIndicator->deleteLater();
264
void SemanticInfoContextManagerItem::update() {
265
KFileItemList itemList = contextManager()->selectedFileItemList();
270
SortedDirModel* dirModel = contextManager()->dirModel();
272
// This hash stores for how many items the tag is present
273
// If you have 3 items, and only 2 have the "Holiday" tag,
274
// then tagHash["Holiday"] will be 2 at the end of the loop.
275
typedef QHash<QString, int> TagHash;
278
Q_FOREACH(const KFileItem& item, itemList) {
279
QModelIndex index = dirModel->indexForItem(item);
281
QVariant value = dirModel->data(index, SemanticInfoDirModel::RatingRole);
283
rating = ratingForVariant(value);
284
} else if (rating != ratingForVariant(value)) {
285
// Ratings aren't the same, reset
289
QString indexDescription = index.data(SemanticInfoDirModel::DescriptionRole).toString();
291
description = indexDescription;
292
} else if (description != indexDescription) {
296
// Fill tagHash, incrementing the tag count if it's already there
297
TagSet tagSet = TagSet::fromVariant(index.data(SemanticInfoDirModel::TagsRole));
298
Q_FOREACH(const QString& tag, tagSet) {
299
TagHash::Iterator it = tagHash.find(tag);
300
if (it == tagHash.end()) {
310
SignalBlocker blocker(d->mRatingWidget);
311
d->mRatingWidget->setRating(rating);
313
d->mDescriptionTextEdit->setText(description);
315
// Init tagInfo from tagHash
317
int itemCount = itemList.count();
318
TagHash::ConstIterator
319
it = tagHash.constBegin(),
320
end = tagHash.constEnd();
321
for (; it!=end; ++it) {
322
QString tag = it.key();
323
int count = it.value();
324
d->mTagInfo[tag] = count == itemCount;
327
bool enabled = !contextManager()->selectedFileItemList().isEmpty();
328
Q_FOREACH(KAction* action, d->mActions) {
329
action->setEnabled(enabled);
332
if (d->mSemanticInfoDialog) {
333
d->updateSemanticInfoDialog();
338
void SemanticInfoContextManagerItem::slotRatingChanged(int rating) {
339
KFileItemList itemList = contextManager()->selectedFileItemList();
341
// Show rating indicator in view mode, and only if sidebar is not visible
342
if (d->mDocumentPanel->isVisible() && !d->mRatingWidget->isVisible()) {
343
delete d->mRatingIndicator.data();
344
d->mRatingIndicator = new RatingIndicator(d->mDocumentPanel->documentView());
345
d->mRatingIndicator->setRating(rating);
346
d->mRatingIndicator->show();
349
SortedDirModel* dirModel = contextManager()->dirModel();
350
Q_FOREACH(const KFileItem& item, itemList) {
351
QModelIndex index = dirModel->indexForItem(item);
352
dirModel->setData(index, rating, SemanticInfoDirModel::RatingRole);
357
void SemanticInfoContextManagerItem::storeDescription() {
358
if (!d->mDescriptionTextEdit->document()->isModified()) {
361
d->mDescriptionTextEdit->document()->setModified(false);
362
QString description = d->mDescriptionTextEdit->toPlainText();
363
KFileItemList itemList = contextManager()->selectedFileItemList();
365
SortedDirModel* dirModel = contextManager()->dirModel();
366
Q_FOREACH(const KFileItem& item, itemList) {
367
QModelIndex index = dirModel->indexForItem(item);
368
dirModel->setData(index, description, SemanticInfoDirModel::DescriptionRole);
373
void SemanticInfoContextManagerItem::assignTag(const SemanticInfoTag& tag) {
374
KFileItemList itemList = contextManager()->selectedFileItemList();
376
SortedDirModel* dirModel = contextManager()->dirModel();
377
Q_FOREACH(const KFileItem& item, itemList) {
378
QModelIndex index = dirModel->indexForItem(item);
379
TagSet tags = TagSet::fromVariant( dirModel->data(index, SemanticInfoDirModel::TagsRole) );
380
if (!tags.contains(tag)) {
382
dirModel->setData(index, tags.toVariant(), SemanticInfoDirModel::TagsRole);
388
void SemanticInfoContextManagerItem::removeTag(const SemanticInfoTag& tag) {
389
KFileItemList itemList = contextManager()->selectedFileItemList();
391
SortedDirModel* dirModel = contextManager()->dirModel();
392
Q_FOREACH(const KFileItem& item, itemList) {
393
QModelIndex index = dirModel->indexForItem(item);
394
TagSet tags = TagSet::fromVariant( dirModel->data(index, SemanticInfoDirModel::TagsRole) );
395
if (tags.contains(tag)) {
397
dirModel->setData(index, tags.toVariant(), SemanticInfoDirModel::TagsRole);
403
void SemanticInfoContextManagerItem::showSemanticInfoDialog() {
404
if (!d->mSemanticInfoDialog) {
405
d->mSemanticInfoDialog = new SemanticInfoDialog(d->mGroup);
406
d->mSemanticInfoDialog->setAttribute(Qt::WA_DeleteOnClose, true);
408
connect(d->mSemanticInfoDialog->mPreviousButton, SIGNAL(clicked()),
409
d->mActionCollection->action("go_previous"), SLOT(trigger()) );
410
connect(d->mSemanticInfoDialog->mNextButton, SIGNAL(clicked()),
411
d->mActionCollection->action("go_next"), SLOT(trigger()) );
412
connect(d->mSemanticInfoDialog->mButtonBox, SIGNAL(rejected()),
413
d->mSemanticInfoDialog, SLOT(close()));
415
AbstractSemanticInfoBackEnd* backEnd = contextManager()->dirModel()->semanticInfoBackEnd();
416
d->mSemanticInfoDialog->mTagWidget->setSemanticInfoBackEnd(backEnd);
417
connect(d->mSemanticInfoDialog->mTagWidget, SIGNAL(tagAssigned(const SemanticInfoTag&)),
418
SLOT(assignTag(const SemanticInfoTag&)) );
419
connect(d->mSemanticInfoDialog->mTagWidget, SIGNAL(tagRemoved(const SemanticInfoTag&)),
420
SLOT(removeTag(const SemanticInfoTag&)) );
422
d->updateSemanticInfoDialog();
423
d->mSemanticInfoDialog->show();
427
bool SemanticInfoContextManagerItem::eventFilter(QObject*, QEvent* event) {
428
if (event->type() == QEvent::FocusOut) {
225
, d(new SemanticInfoContextManagerItemPrivate)
228
d->mActionCollection = actionCollection;
229
d->mViewMainPage = documentPanel;
231
connect(contextManager(), SIGNAL(selectionChanged()),
232
SLOT(slotSelectionChanged()));
233
connect(contextManager(), SIGNAL(selectionDataChanged()),
235
connect(contextManager(), SIGNAL(currentDirUrlChanged()),
242
SemanticInfoContextManagerItem::~SemanticInfoContextManagerItem()
247
inline int ratingForVariant(const QVariant& variant)
249
if (variant.isValid()) {
250
return variant.toInt();
256
void SemanticInfoContextManagerItem::slotSelectionChanged()
258
if (d->mRatingIndicator) {
259
d->mRatingIndicator->deleteLater();
264
void SemanticInfoContextManagerItem::update()
266
KFileItemList itemList = contextManager()->selectedFileItemList();
271
SortedDirModel* dirModel = contextManager()->dirModel();
273
// This hash stores for how many items the tag is present
274
// If you have 3 items, and only 2 have the "Holiday" tag,
275
// then tagHash["Holiday"] will be 2 at the end of the loop.
276
typedef QHash<QString, int> TagHash;
279
Q_FOREACH(const KFileItem & item, itemList) {
280
QModelIndex index = dirModel->indexForItem(item);
282
QVariant value = dirModel->data(index, SemanticInfoDirModel::RatingRole);
284
rating = ratingForVariant(value);
285
} else if (rating != ratingForVariant(value)) {
286
// Ratings aren't the same, reset
290
QString indexDescription = index.data(SemanticInfoDirModel::DescriptionRole).toString();
292
description = indexDescription;
293
} else if (description != indexDescription) {
297
// Fill tagHash, incrementing the tag count if it's already there
298
TagSet tagSet = TagSet::fromVariant(index.data(SemanticInfoDirModel::TagsRole));
299
Q_FOREACH(const QString & tag, tagSet) {
300
TagHash::Iterator it = tagHash.find(tag);
301
if (it == tagHash.end()) {
311
SignalBlocker blocker(d->mRatingWidget);
312
d->mRatingWidget->setRating(rating);
314
d->mDescriptionTextEdit->setText(description);
316
// Init tagInfo from tagHash
318
int itemCount = itemList.count();
319
TagHash::ConstIterator
320
it = tagHash.constBegin(),
321
end = tagHash.constEnd();
322
for (; it != end; ++it) {
323
QString tag = it.key();
324
int count = it.value();
325
d->mTagInfo[tag] = count == itemCount;
328
bool enabled = !contextManager()->selectedFileItemList().isEmpty();
329
Q_FOREACH(KAction * action, d->mActions) {
330
action->setEnabled(enabled);
333
if (d->mSemanticInfoDialog) {
334
d->updateSemanticInfoDialog();
338
void SemanticInfoContextManagerItem::slotRatingChanged(int rating)
340
KFileItemList itemList = contextManager()->selectedFileItemList();
342
// Show rating indicator in view mode, and only if sidebar is not visible
343
if (d->mViewMainPage->isVisible() && !d->mRatingWidget->isVisible()) {
344
delete d->mRatingIndicator.data();
346
//d->mRatingIndicator = new RatingIndicator(d->mViewMainPage->documentView());
347
d->mRatingIndicator = new RatingIndicator(d->mViewMainPage);
348
d->mRatingIndicator->setRating(rating);
349
d->mRatingIndicator->show();
352
SortedDirModel* dirModel = contextManager()->dirModel();
353
Q_FOREACH(const KFileItem & item, itemList) {
354
QModelIndex index = dirModel->indexForItem(item);
355
dirModel->setData(index, rating, SemanticInfoDirModel::RatingRole);
359
void SemanticInfoContextManagerItem::storeDescription()
361
if (!d->mDescriptionTextEdit->document()->isModified()) {
364
d->mDescriptionTextEdit->document()->setModified(false);
365
QString description = d->mDescriptionTextEdit->toPlainText();
366
KFileItemList itemList = contextManager()->selectedFileItemList();
368
SortedDirModel* dirModel = contextManager()->dirModel();
369
Q_FOREACH(const KFileItem & item, itemList) {
370
QModelIndex index = dirModel->indexForItem(item);
371
dirModel->setData(index, description, SemanticInfoDirModel::DescriptionRole);
375
void SemanticInfoContextManagerItem::assignTag(const SemanticInfoTag& tag)
377
KFileItemList itemList = contextManager()->selectedFileItemList();
379
SortedDirModel* dirModel = contextManager()->dirModel();
380
Q_FOREACH(const KFileItem & item, itemList) {
381
QModelIndex index = dirModel->indexForItem(item);
382
TagSet tags = TagSet::fromVariant(dirModel->data(index, SemanticInfoDirModel::TagsRole));
383
if (!tags.contains(tag)) {
385
dirModel->setData(index, tags.toVariant(), SemanticInfoDirModel::TagsRole);
390
void SemanticInfoContextManagerItem::removeTag(const SemanticInfoTag& tag)
392
KFileItemList itemList = contextManager()->selectedFileItemList();
394
SortedDirModel* dirModel = contextManager()->dirModel();
395
Q_FOREACH(const KFileItem & item, itemList) {
396
QModelIndex index = dirModel->indexForItem(item);
397
TagSet tags = TagSet::fromVariant(dirModel->data(index, SemanticInfoDirModel::TagsRole));
398
if (tags.contains(tag)) {
400
dirModel->setData(index, tags.toVariant(), SemanticInfoDirModel::TagsRole);
405
void SemanticInfoContextManagerItem::showSemanticInfoDialog()
407
if (!d->mSemanticInfoDialog) {
408
d->mSemanticInfoDialog = new SemanticInfoDialog(d->mGroup);
409
d->mSemanticInfoDialog->setAttribute(Qt::WA_DeleteOnClose, true);
411
connect(d->mSemanticInfoDialog->mPreviousButton, SIGNAL(clicked()),
412
d->mActionCollection->action("go_previous"), SLOT(trigger()));
413
connect(d->mSemanticInfoDialog->mNextButton, SIGNAL(clicked()),
414
d->mActionCollection->action("go_next"), SLOT(trigger()));
415
connect(d->mSemanticInfoDialog->mButtonBox, SIGNAL(rejected()),
416
d->mSemanticInfoDialog, SLOT(close()));
418
AbstractSemanticInfoBackEnd* backEnd = contextManager()->dirModel()->semanticInfoBackEnd();
419
d->mSemanticInfoDialog->mTagWidget->setSemanticInfoBackEnd(backEnd);
420
connect(d->mSemanticInfoDialog->mTagWidget, SIGNAL(tagAssigned(SemanticInfoTag)),
421
SLOT(assignTag(SemanticInfoTag)));
422
connect(d->mSemanticInfoDialog->mTagWidget, SIGNAL(tagRemoved(SemanticInfoTag)),
423
SLOT(removeTag(SemanticInfoTag)));
425
d->updateSemanticInfoDialog();
426
d->mSemanticInfoDialog->show();
429
bool SemanticInfoContextManagerItem::eventFilter(QObject*, QEvent* event)
431
if (event->type() == QEvent::FocusOut) {