Seamly2D
Code documentation
vfilepropertyeditor.cpp
Go to the documentation of this file.
1 /************************************************************************
2  **
3  ** @file vfilepropertyeditor.cpp
4  ** @author hedgeware <internal(at)hedgeware.net>
5  ** @date
6  **
7  ** @brief
8  ** @copyright
9  ** All rights reserved. This program and the accompanying materials
10  ** are made available under the terms of the GNU Lesser General Public License
11  ** (LGPL) version 2.1 which accompanies this distribution, and is available at
12  ** http://www.gnu.org/licenses/lgpl-2.1.html
13  **
14  ** This library is distributed in the hope that it will be useful,
15  ** but WITHOUT ANY WARRANTY; without even the implied warranty of
16  ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17  ** Lesser General Public License for more details.
18  **
19  *************************************************************************/
20 
21 #include "vfilepropertyeditor.h"
22 
23 #include <QDragEnterEvent>
24 #include <QDragLeaveEvent>
25 #include <QDragMoveEvent>
26 #include <QDropEvent>
27 #include <QEvent>
28 #include <QFile>
29 #include <QFileDialog>
30 #include <QFileInfo>
31 #include <QHBoxLayout>
32 #include <QLineEdit>
33 #include <QList>
34 #include <QMimeData>
35 #include <QRegExp>
36 #include <QSizePolicy>
37 #include <QToolButton>
38 #include <QUrl>
39 #include <Qt>
40 
41 VPE::VFileEditWidget::VFileEditWidget(QWidget *parent, bool is_directory)
42  : QWidget(parent), CurrentFilePath(), ToolButton(nullptr), FileLineEdit(nullptr), FileDialogFilter(), FilterList(),
43  Directory(is_directory)
44 {
45  // Create the tool button,ToolButton = new QToolButton(this);
46  ToolButton = new QToolButton(this);
47  ToolButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Ignored);
48  ToolButton->setText("...");
49  ToolButton->setFixedWidth(20);
50  ToolButton->installEventFilter(this);
51  setFocusProxy(ToolButton); // Make the ToolButton the focus proxy
52  setFocusPolicy(ToolButton->focusPolicy());
53  connect(ToolButton, &QToolButton::clicked, this, &VFileEditWidget::onToolButtonClicked);
54 
55  // Create the line edit widget
56  FileLineEdit = new QLineEdit(this);
57  FileLineEdit->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
58  FileLineEdit->setText(CurrentFilePath);
59  FileLineEdit->installEventFilter(this);
60 
61  // The layout (a horizontal layout)
62  QHBoxLayout* layout = new QHBoxLayout(this);
63  layout->setSpacing(0);
64  layout->setMargin(0);
65  layout->addWidget(FileLineEdit);
66  layout->addWidget(ToolButton);
67 
68  // Accept drops
69  setAcceptDrops(true);
70 }
71 
72 
74 {
75  // nothing needs to be done here
76 }
77 
78 
79 void VPE::VFileEditWidget::setFile(const QString &value, bool emit_signal)
80 {
81  if (CurrentFilePath != value)
82  {
83  CurrentFilePath = value;
84  FileLineEdit->setText(CurrentFilePath);
85 
86  if (emit_signal)
87  {
88  emit dataChangedByUser(CurrentFilePath, this);
89  emit commitData(this);
90  }
91  }
92 }
93 
94 
95 void VPE::VFileEditWidget::setFilter(const QString &dialog_filter, const QStringList& filter_list)
96 {
97  FileDialogFilter = dialog_filter;
98  FilterList = filter_list;
99 }
100 
102 {
103  Directory = dir;
104 }
105 
107 {
108  return CurrentFilePath;
109 }
110 
111 
113 {
114  QString filepath = (Directory ? QFileDialog::getExistingDirectory(nullptr, tr("Directory"), CurrentFilePath,
115  QFileDialog::ShowDirsOnly
116  | QFileDialog::DontUseNativeDialog)
117  : QFileDialog::getOpenFileName(nullptr, tr("Open File"), CurrentFilePath,
118  FileDialogFilter, nullptr,
119  QFileDialog::DontUseNativeDialog));
120  if (filepath.isNull() == false)
121  {
122  setFile(filepath, true);
123  }
124 }
125 
126 
127 bool VPE::VFileEditWidget::eventFilter(QObject *obj, QEvent *ev)
128 {
129  if (ev->type() == QEvent::DragEnter || ev->type() == QEvent::Drop)
130  {
131  ev->ignore();
132  if (ev->type() == QEvent::DragEnter)
133  {
134  dragEnterEvent(static_cast<QDragEnterEvent*>(ev));
135  }
136  else if (ev->type() == QEvent::Drop)
137  {
138  dropEvent(static_cast<QDropEvent*>(ev));
139  }
140 
141  if (ev->isAccepted())
142  {
143  return true;
144  }
145  else
146  return QWidget::eventFilter(obj, ev);
147  }
148  else if (obj == ToolButton && ev->type() == QEvent::KeyPress)
149  {
150  // Ignore the event, so that eventually the delegate gets the event.
151  ev->ignore();
152  return true;
153  }
154  else if (obj == FileLineEdit)
155  {
156  if (ev->type() == QEvent::FocusOut)
157  {
158  setFile(FileLineEdit->text(), true);
159  // We don't return true here because we still want the line edit to catch the event as well
160  }
161  }
162 
163  // forward the signal to the parent class
164  return QWidget::eventFilter(obj, ev);
165 }
166 
168 {
169  return Directory;
170 }
171 
172 
173 void VPE::VFileEditWidget::dragEnterEvent(QDragEnterEvent* event)
174 {
175  QString tmpFileName;
176  if (checkMimeData(event->mimeData(), tmpFileName))
177  {
178  event->accept();
179  event->acceptProposedAction();
180  }
181 }
182 
183 // cppcheck-suppress unusedFunction
184 void VPE::VFileEditWidget::dragMoveEvent(QDragMoveEvent* event)
185 {
186  event->acceptProposedAction();
187 }
188 
189 // cppcheck-suppress unusedFunction
190 void VPE::VFileEditWidget::dragLeaveEvent(QDragLeaveEvent* event)
191 {
192  event->accept();
193 }
194 
195 void VPE::VFileEditWidget::dropEvent(QDropEvent* event)
196 {
197  QString tmpFileName;
198  if (checkMimeData(event->mimeData(), tmpFileName))
199  {
200  setFile(tmpFileName);
201  emit dataChangedByUser(getFile(), this);
202  emit commitData(this);
203  event->accept();
204  event->acceptProposedAction();
205  }
206 }
207 
208 
209 bool VPE::VFileEditWidget::checkMimeData(const QMimeData* data, QString& file) const
210 {
211  if (data->hasUrls())
212  {
213  QList<QUrl> tmpUrlList = data->urls();
214  QFileInfo tmpFileInfo;
215 
216  foreach(QUrl tmpUrl, tmpUrlList)
217  if (QFile::exists(tmpUrl.toLocalFile()))
218  {
219  tmpFileInfo = QFileInfo(tmpUrl.toLocalFile()); break;
220  }
221 
222  if (checkFileFilter(tmpFileInfo.fileName()))
223  {
224  file = tmpFileInfo.absoluteFilePath();
225  return true;
226  }
227  }
228 
229  return false;
230 }
231 
232 bool VPE::VFileEditWidget::checkFileFilter(const QString& file) const
233 {
234  if (FilterList.isEmpty())
235  {
236  return true;
237  }
238 
239  QFileInfo tmpFileInfo(file);
240 
241  if ((Directory && !tmpFileInfo.isDir()) || (!Directory && !tmpFileInfo.isFile()))
242  {
243  return false;
244  }
245 
246  foreach(QString tmpFilter, FilterList)
247  {
248  QRegExp tmpRegExpFilter(tmpFilter, Qt::CaseInsensitive, QRegExp::Wildcard);
249  if (tmpRegExpFilter.exactMatch(file))
250  {
251  return true;
252  }
253  }
254 
255  return false;
256 }
virtual void dragLeaveEvent(QDragLeaveEvent *event) Q_DECL_OVERRIDE
virtual void dragEnterEvent(QDragEnterEvent *event) Q_DECL_OVERRIDE
void onToolButtonClicked()
This slot gets activated, when the "..." button gets clicked.
virtual ~VFileEditWidget() Q_DECL_OVERRIDE
void setDirectory(bool dir)
Sets whether the property stores a directory or a file.
virtual void dragMoveEvent(QDragMoveEvent *event) Q_DECL_OVERRIDE
VFileEditWidget(QWidget *parent, bool is_directory=false)
virtual bool eventFilter(QObject *obj, QEvent *ev) Q_DECL_OVERRIDE
Needed for proper event handling.
virtual void dropEvent(QDropEvent *event) Q_DECL_OVERRIDE
void setFile(const QString &value, bool emit_signal=false)
Sets the current file, does not check if it is valid.
QString getFile() const
This function returns the file currently set to this editor.
virtual bool checkMimeData(const QMimeData *data, QString &file) const
This function checks the mime data, if it is compatible with the filters.
virtual bool checkFileFilter(const QString &file) const
This checks, if a file is compatible with the filters.
void setFilter(const QString &dialog_filter=QString(), const QStringList &filter_list=QStringList())
Sets a filter for the file field.
bool isDirectory()
Returns the directory/file setting.