~ubuntu-branches/ubuntu/precise/gwenview/precise-proposed

« back to all changes in this revision

Viewing changes to lib/semanticinfo/tagwidget.cpp

  • Committer: Package Import Robot
  • Author(s): Jonathan Riddell
  • Date: 2011-12-15 14:17:54 UTC
  • mto: This revision was merged to the branch mainline in revision 12.
  • Revision ID: package-import@ubuntu.com-20111215141754-z043hyx69dulbggf
Tags: upstream-4.7.90
ImportĀ upstreamĀ versionĀ 4.7.90

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
// vim: set tabstop=4 shiftwidth=4 noexpandtab:
 
1
// vim: set tabstop=4 shiftwidth=4 expandtab:
2
2
/*
3
3
Gwenview: an image viewer
4
4
Copyright 2008 AurĆ©lien GĆ¢teau <agateau@kde.org>
40
40
#include <lib/semanticinfo/tagitemdelegate.h>
41
41
#include <lib/semanticinfo/tagmodel.h>
42
42
 
43
 
namespace Gwenview {
44
 
 
45
 
 
46
 
class TagCompleterModel : public QSortFilterProxyModel {
 
43
namespace Gwenview
 
44
{
 
45
 
 
46
class TagCompleterModel : public QSortFilterProxyModel
 
47
{
47
48
public:
48
 
        TagCompleterModel(QObject* parent)
49
 
        : QSortFilterProxyModel(parent)
50
 
        {
51
 
        }
52
 
 
53
 
 
54
 
        void setTagInfo(const TagInfo& tagInfo) {
55
 
                mExcludedTagSet.clear();
56
 
                TagInfo::ConstIterator
57
 
                        it = tagInfo.begin(),
58
 
                        end = tagInfo.end();
59
 
                for(; it!=end; ++it) {
60
 
                        if (it.value()) {
61
 
                                mExcludedTagSet << it.key();
62
 
                        }
63
 
                }
64
 
                invalidate();
65
 
        }
66
 
 
67
 
 
68
 
        void setSemanticInfoBackEnd(AbstractSemanticInfoBackEnd* backEnd) {
69
 
                setSourceModel(TagModel::createAllTagsModel(this, backEnd));
70
 
        }
71
 
 
 
49
    TagCompleterModel(QObject* parent)
 
50
        : QSortFilterProxyModel(parent) {
 
51
    }
 
52
 
 
53
    void setTagInfo(const TagInfo& tagInfo)
 
54
    {
 
55
        mExcludedTagSet.clear();
 
56
        TagInfo::ConstIterator
 
57
        it = tagInfo.begin(),
 
58
        end = tagInfo.end();
 
59
        for (; it != end; ++it) {
 
60
            if (it.value()) {
 
61
                mExcludedTagSet << it.key();
 
62
            }
 
63
        }
 
64
        invalidate();
 
65
    }
 
66
 
 
67
    void setSemanticInfoBackEnd(AbstractSemanticInfoBackEnd* backEnd)
 
68
    {
 
69
        setSourceModel(TagModel::createAllTagsModel(this, backEnd));
 
70
    }
72
71
 
73
72
protected:
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);
78
 
        }
79
 
 
 
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);
 
77
    }
80
78
 
81
79
private:
82
 
        TagSet mExcludedTagSet;
 
80
    TagSet mExcludedTagSet;
83
81
};
84
82
 
85
 
 
86
83
/**
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.
91
88
 */
92
 
class ReturnKeyEater : public QObject {
 
89
class ReturnKeyEater : public QObject
 
90
{
93
91
public:
94
 
        ReturnKeyEater(QObject* parent = 0)
95
 
        : QObject(parent)
96
 
        {}
 
92
    ReturnKeyEater(QObject* parent = 0)
 
93
        : QObject(parent)
 
94
    {}
97
95
 
98
96
protected:
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()) {
103
 
                        case Qt::Key_Return:
104
 
                        case Qt::Key_Enter:
105
 
                                return true;
106
 
                        default:
107
 
                                return false;
108
 
                        }
109
 
                }
110
 
                return false;
111
 
        }
 
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()) {
 
101
            case Qt::Key_Return:
 
102
            case Qt::Key_Enter:
 
103
                return true;
 
104
            default:
 
105
                return false;
 
106
            }
 
107
        }
 
108
        return false;
 
109
    }
112
110
};
113
111
 
114
112
struct TagWidgetPrivate {
115
 
        TagWidget* that;
116
 
        TagInfo mTagInfo;
117
 
        QListView* mListView;
118
 
        QComboBox* mComboBox;
119
 
        KPushButton* mAddButton;
120
 
        AbstractSemanticInfoBackEnd* mBackEnd;
121
 
        TagCompleterModel* mTagCompleterModel;
122
 
        TagModel* mAssignedTagModel;
123
 
 
124
 
 
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);
134
 
 
135
 
                mComboBox = new QComboBox;
136
 
                mComboBox->setEditable(true);
137
 
                mComboBox->setInsertPolicy(QComboBox::NoInsert);
138
 
 
139
 
                mTagCompleterModel = new TagCompleterModel(that);
140
 
                QCompleter* completer = new QCompleter(that);
141
 
                completer->setCaseSensitivity(Qt::CaseInsensitive);
142
 
                completer->setModel(mTagCompleterModel);
143
 
                mComboBox->setCompleter(completer);
144
 
 
145
 
                mComboBox->setModel(mTagCompleterModel);
146
 
 
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()));
152
 
 
153
 
                QVBoxLayout* layout = new QVBoxLayout(that);
154
 
                layout->setMargin(0);
155
 
                layout->addWidget(mListView);
156
 
 
157
 
                QHBoxLayout* hLayout = new QHBoxLayout;
158
 
                hLayout->addWidget(mComboBox);
159
 
                hLayout->addWidget(mAddButton);
160
 
                layout->addLayout(hLayout);
161
 
 
162
 
                that->setTabOrder(mComboBox, mListView);
163
 
        }
164
 
 
165
 
 
166
 
        void fillTagModel() {
167
 
                Q_ASSERT(mBackEnd);
168
 
 
169
 
                mAssignedTagModel->clear();
170
 
                TagInfo::ConstIterator
171
 
                        it = mTagInfo.constBegin(),
172
 
                        end = mTagInfo.constEnd();
173
 
                for(; it!=end; ++it) {
174
 
                        mAssignedTagModel->addTag(
175
 
                                it.key(),
176
 
                                QString(),
177
 
                                it.value() ? TagModel::FullyAssigned : TagModel::PartiallyAssigned);
178
 
                }
179
 
        }
180
 
 
181
 
 
182
 
        void updateCompleterModel() {
183
 
                mTagCompleterModel->setTagInfo(mTagInfo);
184
 
        }
 
113
    TagWidget* q;
 
114
    TagInfo mTagInfo;
 
115
    QListView* mListView;
 
116
    QComboBox* mComboBox;
 
117
    KPushButton* mAddButton;
 
118
    AbstractSemanticInfoBackEnd* mBackEnd;
 
119
    TagCompleterModel* mTagCompleterModel;
 
120
    TagModel* mAssignedTagModel;
 
121
 
 
122
    void setupWidgets()
 
123
    {
 
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);
 
132
 
 
133
        mComboBox = new QComboBox;
 
134
        mComboBox->setEditable(true);
 
135
        mComboBox->setInsertPolicy(QComboBox::NoInsert);
 
136
 
 
137
        mTagCompleterModel = new TagCompleterModel(q);
 
138
        QCompleter* completer = new QCompleter(q);
 
139
        completer->setCaseSensitivity(Qt::CaseInsensitive);
 
140
        completer->setModel(mTagCompleterModel);
 
141
        mComboBox->setCompleter(completer);
 
142
 
 
143
        mComboBox->setModel(mTagCompleterModel);
 
144
 
 
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()));
 
150
 
 
151
        QVBoxLayout* layout = new QVBoxLayout(q);
 
152
        layout->setMargin(0);
 
153
        layout->addWidget(mListView);
 
154
 
 
155
        QHBoxLayout* hLayout = new QHBoxLayout;
 
156
        hLayout->addWidget(mComboBox);
 
157
        hLayout->addWidget(mAddButton);
 
158
        layout->addLayout(hLayout);
 
159
 
 
160
        q->setTabOrder(mComboBox, mListView);
 
161
    }
 
162
 
 
163
    void fillTagModel()
 
164
    {
 
165
        Q_ASSERT(mBackEnd);
 
166
 
 
167
        mAssignedTagModel->clear();
 
168
        TagInfo::ConstIterator
 
169
        it = mTagInfo.constBegin(),
 
170
        end = mTagInfo.constEnd();
 
171
        for (; it != end; ++it) {
 
172
            mAssignedTagModel->addTag(
 
173
                it.key(),
 
174
                QString(),
 
175
                it.value() ? TagModel::FullyAssigned : TagModel::PartiallyAssigned);
 
176
        }
 
177
    }
 
178
 
 
179
    void updateCompleterModel()
 
180
    {
 
181
        mTagCompleterModel->setTagInfo(mTagInfo);
 
182
    }
185
183
};
186
184
 
187
 
 
188
185
TagWidget::TagWidget(QWidget* parent)
189
186
: QWidget(parent)
190
 
, d(new TagWidgetPrivate) {
191
 
        d->that = this;
192
 
        d->mBackEnd = 0;
193
 
        d->mAssignedTagModel = new TagModel(this);
194
 
        d->setupWidgets();
195
 
        installEventFilter(new ReturnKeyEater(this));
196
 
 
197
 
        connect(d->mComboBox->lineEdit(), SIGNAL(returnPressed()),
198
 
                SLOT(addTagFromComboBox()) );
199
 
}
200
 
 
201
 
 
202
 
TagWidget::~TagWidget() {
203
 
        delete d;
204
 
}
205
 
 
206
 
 
207
 
void TagWidget::setSemanticInfoBackEnd(AbstractSemanticInfoBackEnd* backEnd) {
208
 
        d->mBackEnd = backEnd;
209
 
        d->mAssignedTagModel->setSemanticInfoBackEnd(backEnd);
210
 
        d->mTagCompleterModel->setSemanticInfoBackEnd(backEnd);
211
 
}
212
 
 
213
 
 
214
 
void TagWidget::setTagInfo(const TagInfo& tagInfo) {
215
 
        d->mTagInfo = tagInfo;
216
 
        d->fillTagModel();
217
 
        d->updateCompleterModel();
218
 
}
219
 
 
220
 
 
221
 
void TagWidget::addTagFromComboBox() {
222
 
        Q_ASSERT(d->mBackEnd);
223
 
        QString label = d->mComboBox->currentText();
224
 
        if (label.isEmpty()) {
225
 
                return;
226
 
        }
227
 
        assignTag(d->mBackEnd->tagForLabel(label.trimmed()));
228
 
 
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
231
 
        // model is empty.
232
 
        QTimer::singleShot(0, d->mComboBox, SLOT(clearEditText()));
233
 
}
234
 
 
235
 
 
236
 
void TagWidget::assignTag(const SemanticInfoTag& tag) {
237
 
        d->mTagInfo[tag] = true;
238
 
        d->mAssignedTagModel->addTag(tag);
239
 
        d->updateCompleterModel();
240
 
 
241
 
        emit tagAssigned(tag);
242
 
}
243
 
 
244
 
 
245
 
void TagWidget::removeTag(const SemanticInfoTag& tag) {
246
 
        d->mTagInfo.remove(tag);
247
 
        d->mAssignedTagModel->removeTag(tag);
248
 
        d->updateCompleterModel();
249
 
 
250
 
        emit tagRemoved(tag);
251
 
}
252
 
 
 
187
, d(new TagWidgetPrivate)
 
188
{
 
189
    d->q = this;
 
190
    d->mBackEnd = 0;
 
191
    d->mAssignedTagModel = new TagModel(this);
 
192
    d->setupWidgets();
 
193
    installEventFilter(new ReturnKeyEater(this));
 
194
 
 
195
    connect(d->mComboBox->lineEdit(), SIGNAL(returnPressed()),
 
196
            SLOT(addTagFromComboBox()));
 
197
}
 
198
 
 
199
TagWidget::~TagWidget()
 
200
{
 
201
    delete d;
 
202
}
 
203
 
 
204
void TagWidget::setSemanticInfoBackEnd(AbstractSemanticInfoBackEnd* backEnd)
 
205
{
 
206
    d->mBackEnd = backEnd;
 
207
    d->mAssignedTagModel->setSemanticInfoBackEnd(backEnd);
 
208
    d->mTagCompleterModel->setSemanticInfoBackEnd(backEnd);
 
209
}
 
210
 
 
211
void TagWidget::setTagInfo(const TagInfo& tagInfo)
 
212
{
 
213
    d->mTagInfo = tagInfo;
 
214
    d->fillTagModel();
 
215
    d->updateCompleterModel();
 
216
}
 
217
 
 
218
void TagWidget::addTagFromComboBox()
 
219
{
 
220
    Q_ASSERT(d->mBackEnd);
 
221
    QString label = d->mComboBox->currentText();
 
222
    if (label.isEmpty()) {
 
223
        return;
 
224
    }
 
225
    assignTag(d->mBackEnd->tagForLabel(label.trimmed()));
 
226
 
 
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
 
229
    // model is empty.
 
230
    QTimer::singleShot(0, d->mComboBox, SLOT(clearEditText()));
 
231
}
 
232
 
 
233
void TagWidget::assignTag(const SemanticInfoTag& tag)
 
234
{
 
235
    d->mTagInfo[tag] = true;
 
236
    d->mAssignedTagModel->addTag(tag);
 
237
    d->updateCompleterModel();
 
238
 
 
239
    emit tagAssigned(tag);
 
240
}
 
241
 
 
242
void TagWidget::removeTag(const SemanticInfoTag& tag)
 
243
{
 
244
    d->mTagInfo.remove(tag);
 
245
    d->mAssignedTagModel->removeTag(tag);
 
246
    d->updateCompleterModel();
 
247
 
 
248
    emit tagRemoved(tag);
 
249
}
253
250
 
254
251
} // namespace