kwave  18.07.70
FileDialog.cpp
Go to the documentation of this file.
1 /*************************************************************************
2  KwaveFileDialog.cpp - enhanced KFileDialog
3  -------------------
4  begin : Thu May 30 2002
5  copyright : (C) 2002 by Thomas Eschenbacher
6  email : Thomas.Eschenbacher@gmx.de
7  ***************************************************************************/
8 
9 /***************************************************************************
10  * *
11  * This program is free software; you can redistribute it and/or modify *
12  * it under the terms of the GNU General Public License as published by *
13  * the Free Software Foundation; either version 2 of the License, or *
14  * (at your option) any later version. *
15  * *
16  ***************************************************************************/
17 
18 #include "config.h"
19 
20 #include <QFileInfo>
21 #include <QMimeDatabase>
22 #include <QMimeType>
23 #include <QPushButton>
24 #include <QRegExp>
25 #include <QString>
26 #include <QStringList>
27 #include <QUrl>
28 
29 #include <KConfig>
30 #include <KConfigGroup>
31 #include <KFile>
32 #include <KFileFilterCombo>
33 #include <KSharedConfig>
34 
35 #include "libkwave/CodecManager.h"
36 #include "libkwave/String.h"
37 
38 #include "libgui/FileDialog.h"
39 
40 //***************************************************************************
42  const QString &startDir,
43  OperationMode mode,
44  const QString &filter,
45  QWidget *parent,
46  const QUrl last_url,
47  const QString last_ext
48 )
49  :QDialog(parent),
50  m_layout(this),
51  m_file_widget(QUrl::fromUserInput(startDir), this),
52  m_config_group(),
53  m_last_url(last_url),
54  m_last_ext(last_ext)
55 {
56  const bool saving = (mode == SaveFile);
57 
58  // do some layout and init stuff
59  m_layout.addWidget(&m_file_widget);
60  setMinimumSize(m_file_widget.dialogSizeHint());
61  setModal(true);
62  connect(&m_file_widget, SIGNAL(filterChanged(QString)),
63  this, SIGNAL(filterChanged(QString)));
64 
65  // connect the Cancel button
66  QPushButton *button;
67  button = m_file_widget.cancelButton();
68  connect(button, SIGNAL(clicked()), this, SLOT(reject()));
69  button->show();
70 
71  // connect the Open/Save button
72  button = m_file_widget.okButton();
73  connect(&m_file_widget, SIGNAL(accepted()), this, SLOT(accept()));
74  connect(button, SIGNAL(clicked(bool)), &m_file_widget, SLOT(slotOk()));
75  button->show();
76 
77  switch (mode) {
78  case SaveFile:
79  m_file_widget.setOperationMode(KFileWidget::Saving);
80  m_file_widget.setMode(KFile::File);
81  m_file_widget.setConfirmOverwrite(false);
82  break;
83  case OpenFile:
84  m_file_widget.setOperationMode(KFileWidget::Opening);
85  m_file_widget.setMode(KFile::File |
86  KFile::ExistingOnly);
87  break;
88  case SelectDir:
89  m_file_widget.setOperationMode(KFileWidget::Opening);
90  m_file_widget.setMode(KFile::Directory |
91  KFile::ExistingOnly);
92  break;
93  }
94 
95  QString special_prefix = _("kfiledialog:///");
96  if (startDir.startsWith(special_prefix)) {
97  // configuration key given
98  m_file_widget.setKeepLocation(true);
99 
100  // load initial settings
101  QString section = startDir;
102  section = section.remove(0, special_prefix.length());
103  if (section.contains(_("/")))
104  section = section.left(section.indexOf(_("/")));
105  section.prepend(_("KwaveFileDialog-"));
106  loadConfig(section);
107  }
108 
109  // if a file extension was passed but no filter, try to guess
110  // the mime type
111  QString file_filter = filter;
112  if (!file_filter.length() && m_last_ext.length()) {
113  file_filter = guessFilterFromFileExt(m_last_ext, mode);
114  qDebug("guessed filter for '%s': '%s",
115  DBG(m_last_ext), DBG(file_filter));
116  }
117 
118  // if a filename or directory URL was passed, try to re-use it
119  if (!m_last_url.isEmpty() && (m_last_url.isLocalFile() || saving)) {
120  QFileInfo file(m_last_url.toLocalFile());
121  if (QFileInfo(file.path()).exists() || saving)
122  m_file_widget.setUrl(m_last_url.adjusted(QUrl::RemoveFilename));
123  if (!file.isDir() && (file.exists() || saving))
124  m_file_widget.setSelectedUrl(
125  QUrl::fromLocalFile(m_last_url.fileName()));
126  }
127 
128  // parse the list of file filters and put the last extension on top
129  if (file_filter.length()) {
130  QStringList filter_list = file_filter.split(_("\n"));
131  QStringList name_filters;
132  QString best_filter;
133  QString best_pattern;
134  foreach (const QString &filter_item, filter_list) {
135  QString f(filter_item);
136  QString p(_("*"));
137  if (f.contains(_("|"))) {
138  int i = f.indexOf(_("|"));
139  p = f.left(i);
140  f = f.mid(i + 1);
141  }
142  if (!f.length()) continue;
143 
144  // put the last extension to the top of the list
145  // and thus make it selected
146  if (m_last_ext.length()) {
147  QStringList extensions = p.split(_(" "));
148  if (extensions.contains(m_last_ext)) {
149  if (!best_filter.length() ||
150  (p.length() <= best_pattern.length())) {
151  best_filter = filter_item;
152  best_pattern = p;
153  }
154  }
155  }
156 
157  name_filters.append(filter_item);
158  }
159  if (best_filter.length()) {
160  name_filters.removeAll(best_filter);
161  name_filters.prepend(best_filter);
162  }
163 
164  m_file_widget.setFilter(name_filters.join(QChar::fromLatin1('\n')));
165  }
166 }
167 
168 //***************************************************************************
169 void Kwave::FileDialog::loadConfig(const QString &section)
170 {
171  if (!section.length()) return;
172  KConfigGroup cfg = KSharedConfig::openConfig()->group(section);
173  m_config_group = section;
174  if (!m_last_url.isEmpty()) {
175  QUrl last_path = cfg.readEntry("last_url", m_last_url);
176  if (!last_path.isEmpty()) {
177  // take last path, but user defined file name
178  QString file_name = m_last_url.fileName();
179  last_path = last_path.adjusted(QUrl::RemoveFilename);
180  m_last_url = QUrl::fromUserInput(last_path.path() + file_name);
181  }
182  } else {
183  m_last_url = QUrl::fromUserInput(cfg.readEntry("last_url",
184  m_last_url.toDisplayString()));
185  }
186  if (!m_last_ext.length())
187  m_last_ext = cfg.readEntry("last_ext", m_last_ext);
188 
189  // get last dialog size (Kwave global config)
190  cfg = KSharedConfig::openConfig()->group("FileDialog");
191  int w = cfg.readEntry("dialog_width", sizeHint().width());
192  int h = cfg.readEntry("dialog_height", sizeHint().height());
193  if (w < minimumWidth()) w = sizeHint().width();
194  if (h < minimumHeight()) w = sizeHint().height();
195  resize(w, h);
196 }
197 
198 //***************************************************************************
200 {
201  if (!m_config_group.length()) return;
202  if (selectedUrl().isEmpty()) return;
203 
204  QString file_name = selectedUrl().fileName();
205  if (!file_name.length()) return; // aborted
206 
207  // store the last URL
208  m_last_url = m_file_widget.baseUrl();
209 
210  // store the last extension if present
211  QFileInfo file(file_name);
212  QString extension = file.suffix();
213  if (extension.length()) {
214  // simple case: file extension
215  m_last_ext = _("*.") + extension;
216  } else {
217  // tricky case: filename mask
218  QString pattern = m_file_widget.currentFilter();
219  if (pattern.contains(_("|"))) {
220  int i = pattern.indexOf(_("|"));
221  pattern = pattern.left(i);
222  }
223  m_last_ext = _("");
224  foreach (const QString &mask, pattern.split(_(" "))) {
225  QRegExp regex(mask, Qt::CaseSensitive, QRegExp::Wildcard);
226  if (regex.indexIn(file_name) >= 0) {
227  m_last_ext = mask;
228  break;
229  }
230  }
231  }
232 
233  KConfigGroup cfg = KSharedConfig::openConfig()->group(m_config_group);
234  cfg.writeEntry("last_url", m_last_url);
235  cfg.writeEntry("last_ext", m_last_ext);
236  cfg.sync();
237 
238  // save the geometry of the dialog (Kwave global config)
239  cfg = KSharedConfig::openConfig()->group("FileDialog");
240  cfg.writeEntry("dialog_width", width());
241  cfg.writeEntry("dialog_height", height());
242  cfg.sync();
243 }
244 
245 //***************************************************************************
247 {
248  QStringList ext_list = m_file_widget.currentFilter().split(_(" "));
249  return *(ext_list.begin());
250 }
251 
252 //***************************************************************************
254 {
255  return m_file_widget.selectedUrl();
256 }
257 
258 //***************************************************************************
260 {
261  return m_file_widget.baseUrl();
262 }
263 
264 //***************************************************************************
265 void Kwave::FileDialog::setDirectory(const QString &directory)
266 {
267  m_file_widget.setStartDir(QUrl::fromUserInput(directory));
268 }
269 
270 //***************************************************************************
271 void Kwave::FileDialog::selectUrl(const QUrl &url)
272 {
273  m_file_widget.setUrl(url);
274 }
275 
276 //***************************************************************************
278 {
279  m_file_widget.accept();
280 
281  // save the configuration when the dialog was accepted
282  saveConfig();
283 
284  QDialog::accept();
285 }
286 
287 //***************************************************************************
288 QString Kwave::FileDialog::guessFilterFromFileExt(const QString &pattern,
289  OperationMode mode)
290 {
291  // if there are multiple extensions in a list, iterate over them
292  if (pattern.contains(_(" "))) {
293  QStringList patterns = pattern.split(_(" "));
294  foreach (const QString &p, patterns) {
295  QString f = guessFilterFromFileExt(p, mode);
296  if (f.length()) return f;
297  }
298  }
299 
300  // get the filter list of our own codecs, this prefers the Kwave internal
301  // mime types against the ones from KDE
302  QString filters = (mode == SaveFile) ?
305  foreach (const QString &filter, filters.split(_(" "))) {
306  QString p = filter;
307  if (p.contains(_("|"))) {
308  int i = p.indexOf(_("|"));
309  p = p.left(i);
310  }
311  foreach (const QString &mask, p.split(_(" "))) {
312  if (mask == pattern) {
313 // qDebug("MATCH from CodecManager: '%s' matches '%s' -> '%s'",
314 // DBG(mask), DBG(pattern), DBG(filter));
315  return filter;
316  }
317  }
318  }
319 
320  // try to find out by asking the Qt mime database
321  QMimeDatabase db;
322  QList<QMimeType> mime_types = db.mimeTypesForFileName(pattern);
323  if (!mime_types.isEmpty()) {
324  foreach (const QMimeType &m, mime_types) {
325  if (m.isValid() && !m.isDefault()) {
326  QString filter_string =
327  m.globPatterns().join(_(" ")) + _("|") +
328  m.filterString();
329 // qDebug("MATCH from QMimeDatabase: '%s' -> '%s'",
330 // DBG(pattern), DBG(filter_string));
331  return filter_string;
332  }
333  }
334  }
335 
336  return QString();
337 }
338 
339 //***************************************************************************
341 {
342  m_file_widget.setCustomWidget(widget);
343 }
344 
345 //***************************************************************************
346 KUrlComboBox *Kwave::FileDialog::locationEdit() const
347 {
348  return m_file_widget.locationEdit();
349 }
350 
351 //***************************************************************************
352 //***************************************************************************
static QString encodingFilter()
QUrl selectedUrl() const
Definition: FileDialog.cpp:253
KUrlComboBox * locationEdit() const
Definition: FileDialog.cpp:346
FileDialog(const QString &startDir, OperationMode mode, const QString &filter, QWidget *parent, const QUrl last_url=QUrl(), const QString last_ext=QString())
Definition: FileDialog.cpp:41
void selectUrl(const QUrl &url)
Definition: FileDialog.cpp:271
void setCustomWidget(QWidget *widget)
Definition: FileDialog.cpp:340
QString selectedExtension()
Definition: FileDialog.cpp:246
KFileWidget m_file_widget
Definition: FileDialog.h:154
void setDirectory(const QString &directory)
Definition: FileDialog.cpp:265
QUrl baseUrl() const
Definition: FileDialog.cpp:259
QVBoxLayout m_layout
Definition: FileDialog.h:151
bool connect(Kwave::StreamObject &source, const char *output, Kwave::StreamObject &sink, const char *input)
Definition: Connect.cpp:48
QString guessFilterFromFileExt(const QString &pattern, OperationMode mode)
Definition: FileDialog.cpp:288
void loadConfig(const QString &section)
Definition: FileDialog.cpp:169
QString m_config_group
Definition: FileDialog.h:157
static QString decodingFilter()
#define _(m)
Definition: memcpy.c:66
#define DBG(qs)
Definition: String.h:55
QString m_last_ext
Definition: FileDialog.h:163
void filterChanged(const QString &filter)
virtual void accept() Q_DECL_OVERRIDE
Definition: FileDialog.cpp:277