LeechCraft  0.6.70-10870-g558588d6ec
Modular cross-platform feature rich live environment.
tagslineedit.cpp
Go to the documentation of this file.
1 /**********************************************************************
2  * LeechCraft - modular cross-platform feature rich internet client.
3  * Copyright (C) 2006-2014 Georg Rudoy
4  *
5  * Boost Software License - Version 1.0 - August 17th, 2003
6  *
7  * Permission is hereby granted, free of charge, to any person or organization
8  * obtaining a copy of the software and accompanying documentation covered by
9  * this license (the "Software") to use, reproduce, display, distribute,
10  * execute, and transmit the Software, and to prepare derivative works of the
11  * Software, and to permit third-parties to whom the Software is furnished to
12  * do so, all subject to the following:
13  *
14  * The copyright notices in the Software and this entire statement, including
15  * the above license grant, this restriction and the following disclaimer,
16  * must be included in all copies of the Software, in whole or in part, and
17  * all derivative works of the Software, unless such copies or derivative
18  * works are solely in the form of machine-executable object code generated by
19  * a source language processor.
20  *
21  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23  * FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
24  * SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
25  * FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
26  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27  * DEALINGS IN THE SOFTWARE.
28  **********************************************************************/
29 
30 #include "tagslineedit.h"
31 #include <QtDebug>
32 #include <QTimer>
33 #include <QCompleter>
34 #include <QContextMenuEvent>
35 #include <QHBoxLayout>
36 #include <QPushButton>
37 #include <QToolButton>
38 #include <QAbstractItemView>
40 #include "tagscompletionmodel.h"
41 #include "tagscompleter.h"
42 
43 namespace LeechCraft
44 {
45 namespace Util
46 {
47  TagsLineEdit::TagsLineEdit (QWidget *parent)
48  : QLineEdit (parent)
49  , Completer_ (0)
50  , Separator_ ("; ")
51  {
52  }
53 
55  {
56  CategorySelector_.reset (new CategorySelector (parentWidget ()));
57  CategorySelector_->SetSeparator (Separator_);
58  CategorySelector_->hide ();
59 
60  QAbstractItemModel *model = Completer_->model ();
61 
62  if (model->metaObject ()->indexOfSignal (QMetaObject::normalizedSignature ("tagsUpdated (QStringList)")) >= 0)
63  connect (model,
64  SIGNAL (tagsUpdated (QStringList)),
65  this,
66  SLOT (handleTagsUpdated (QStringList)));
67 
68  QStringList initialTags;
69  for (int i = 0; i < model->rowCount (); ++i)
70  initialTags << model->data (model->index (i, 0)).toString ();
71  handleTagsUpdated (initialTags);
72 
73  connect (CategorySelector_.get (),
74  SIGNAL (tagsSelectionChanged (const QStringList&)),
75  this,
76  SLOT (handleSelectionChanged (const QStringList&)));
77 
78  connect (this,
79  SIGNAL (textChanged (const QString&)),
80  CategorySelector_.get (),
81  SLOT (lineTextChanged (const QString&)));
82 
83  if (!mgr)
84  mgr = new LineEditButtonManager { this };
85 
86  auto button = new QToolButton { this };
87  button->setIconSize ({ 16, 16 });
88  button->setIcon (QIcon::fromTheme ("mail-tagged"));
89  button->setCursor (Qt::ArrowCursor);
90  button->setStyleSheet ("QToolButton { border: none; padding: 0px; }");
91 
92  mgr->Add (button);
93 
94  connect (button,
95  SIGNAL (clicked ()),
96  this,
97  SLOT (showSelector ()));
98  }
99 
100  QString TagsLineEdit::GetSeparator () const
101  {
102  return Separator_;
103  }
104 
105  void TagsLineEdit::SetSeparator (const QString& sep)
106  {
107  Separator_ = sep;
108  if (CategorySelector_)
109  CategorySelector_->SetSeparator (sep);
110  }
111 
112  void TagsLineEdit::insertTag (const QString& completion)
113  {
114  if (Completer_->widget () != this)
115  return;
116 
117  QString wtext = text ();
118  if (completion.startsWith (wtext))
119  wtext.clear ();
120  int pos = wtext.lastIndexOf (Separator_);
121  if (pos >= 0)
122  wtext = wtext.left (pos).append (Separator_);
123  else
124  wtext.clear ();
125  wtext.append (completion);
126  wtext = wtext.simplified ();
127  setText (wtext);
128 
129  emit tagsChosen ();
130  }
131 
132  void TagsLineEdit::handleTagsUpdated (const QStringList& tags)
133  {
134  CategorySelector_->setPossibleSelections (tags);
135  }
136 
137  void TagsLineEdit::setTags (const QStringList& tags)
138  {
139  setText (tags.join (Separator_));
140  if (CategorySelector_.get ())
141  CategorySelector_->SetSelections (tags);
142  }
143 
144  void TagsLineEdit::handleSelectionChanged (const QStringList& tags)
145  {
146  setText (tags.join (Separator_));
147 
148  emit tagsChosen ();
149  }
150 
151  void TagsLineEdit::showSelector ()
152  {
153  CategorySelector_->move (QCursor::pos ());
154  CategorySelector_->show ();
155  }
156 
157  void TagsLineEdit::keyPressEvent (QKeyEvent *e)
158  {
159  if (Completer_ && Completer_->popup ()->isVisible ())
160  switch (e->key ())
161  {
162  case Qt::Key_Enter:
163  case Qt::Key_Return:
164  case Qt::Key_Escape:
165  case Qt::Key_Tab:
166  case Qt::Key_Backtab:
167  e->ignore ();
168  return;
169  default:
170  break;
171  }
172 
173  QLineEdit::keyPressEvent (e);
174 
175  bool cos = e->modifiers () & (Qt::ControlModifier |
176  Qt::ShiftModifier |
177  Qt::AltModifier |
178  Qt::MetaModifier);
179  bool isShortcut = e->modifiers () & (Qt::ControlModifier |
180  Qt::AltModifier |
181  Qt::ShiftModifier);
182  if (!Completer_ ||
183  (cos && e->text ().isEmpty ()) ||
184  isShortcut)
185  return;
186 
187  QString completionPrefix = textUnderCursor ();
188  Completer_->setCompletionPrefix (completionPrefix);
189  Completer_->popup ()->
190  setCurrentIndex (Completer_->completionModel ()->index (0, 0));
191  Completer_->complete ();
192  }
193 
194  void TagsLineEdit::focusInEvent (QFocusEvent *e)
195  {
196  if (Completer_)
197  Completer_->setWidget (this);
198  QLineEdit::focusInEvent (e);
199  }
200 
201  void TagsLineEdit::contextMenuEvent (QContextMenuEvent *e)
202  {
203  if (!CategorySelector_.get ())
204  {
205  QLineEdit::contextMenuEvent (e);
206  return;
207  }
208 
209  CategorySelector_->move (e->globalPos ());
210  CategorySelector_->show ();
211  }
212 
214  {
215  if (Completer_)
216  disconnect (Completer_,
217  0,
218  this,
219  0);
220 
221  Completer_ = c;
222 
223  if (!Completer_)
224  return;
225 
226  Completer_->setWidget (this);
227  Completer_->setCompletionMode (QCompleter::PopupCompletion);
228  connect (Completer_,
229  SIGNAL (activated (const QString&)),
230  this,
231  SLOT (insertTag (const QString&)));
232  }
233 
234  QString TagsLineEdit::textUnderCursor () const
235  {
236  auto rxStr = Separator_;
237  rxStr.replace (' ', "\\s*");
238 
239  QRegExp rx (rxStr);
240 
241  QString wtext = text ();
242  int pos = cursorPosition () - 1;
243  int last = wtext.indexOf (rx, pos);
244  int first = wtext.lastIndexOf (rx, pos);
245  if (first == -1)
246  first = 0;
247  if (last == -1)
248  last = wtext.size ();
249  return wtext.mid (first, last - first);
250  }
251 }
252 }
detail::ExprTree< detail::ExprType::LeafStaticPlaceholder, boost::mpl::int_< Idx > > pos
Definition: oral.h:922
virtual void keyPressEvent(QKeyEvent *)
QString GetSeparator() const
Returns the separator for the tags.
void handleTagsUpdated(const QStringList &allTags)
Sets thew new list of the available tags.
Manages additional overlay buttons in a QLineEdit.
void insertTag(const QString &string)
Completes the string.
TagsLineEdit(QWidget *parent)
Constructs the line edit widget.
void Add(QToolButton *button)
Adds a button to the line edit.
Completer suitable for tag completion.
Definition: tagscompleter.h:58
void SetSeparator(const QString &)
Sets the separator for the tags.
void SetCompleter(TagsCompleter *)
char * toString(const char *name, const T &t)
Definition: common.h:56
virtual void focusInEvent(QFocusEvent *)
virtual void contextMenuEvent(QContextMenuEvent *)
The CategorySelector widget provides a way to select amongst a group of items.
void setTags(const QStringList &tags)
Sets the currently selected tags.
void AddSelector(LineEditButtonManager *manager=nullptr)
Adds the selector widget to the line edit.