kwave  18.07.70
SaveBlocksPlugin.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  SaveBlocksPlugin.cpp - Plugin for saving blocks between labels
3  -------------------
4  begin : Thu Mar 01 2007
5  copyright : (C) 2007 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 <errno.h>
21 
22 #include <QDir>
23 #include <QFile>
24 #include <QFileInfo>
25 #include <QRegExp>
26 #include <QStringList>
27 
28 #include <KLocalizedString>
29 
30 #include "libkwave/CodecManager.h"
31 #include "libkwave/Encoder.h"
32 #include "libkwave/FileInfo.h"
33 #include "libkwave/Label.h"
34 #include "libkwave/LabelList.h"
35 #include "libkwave/MessageBox.h"
36 #include "libkwave/MetaDataList.h"
37 #include "libkwave/Parser.h"
38 #include "libkwave/SignalManager.h"
39 #include "libkwave/String.h"
40 
41 #include "SaveBlocksDialog.h"
42 #include "SaveBlocksPlugin.h"
43 
44 KWAVE_PLUGIN(saveblocks, SaveBlocksPlugin)
45 
46 //***************************************************************************
48  const QVariantList &args)
49  :Kwave::Plugin(parent, args),
50  m_url(), m_pattern(), m_numbering_mode(CONTINUE),
51  m_selection_only(true), m_block_info()
52 {
53 }
54 
55 //***************************************************************************
57 {
58 }
59 
60 //***************************************************************************
61 QStringList *Kwave::SaveBlocksPlugin::setup(QStringList &previous_params)
62 {
63  // try to interpret the previous parameters
64  interpreteParameters(previous_params);
65 
66  // create the setup dialog
67  sample_index_t selection_left = 0;
68  sample_index_t selection_right = 0;
69  selection(Q_NULLPTR, &selection_left, &selection_right, false);
70 
71  // enable the "selection only" checkbox only if there is something
72  // selected but not everything
73  bool selected_something = (selection_left != selection_right);
74  bool selected_all = ((selection_left == 0) &&
75  (selection_right + 1 >= signalLength()));
76  bool enable_selection_only = selected_something && !selected_all;
77 
78  QString filename = m_url.path();
79  QString base = findBase(filename, m_pattern);
80  scanBlocksToSave(base, m_selection_only && enable_selection_only);
81 
82  QPointer<Kwave::SaveBlocksDialog> dialog =
83  new(std::nothrow) Kwave::SaveBlocksDialog(
84  _("kfiledialog:///kwave_save_blocks"),
86  parentWidget(),
87  QUrl::fromUserInput(signalName()),
88  _("*.wav"),
89  m_pattern,
92  enable_selection_only
93  );
94  if (!dialog) return Q_NULLPTR;
95 
96  // connect the signals/slots from the plugin and the dialog
97  connect(dialog, SIGNAL(sigSelectionChanged(QString,
99  this, SLOT(updateExample(QString,QString,
101  connect(this, SIGNAL(sigNewExample(QString)),
102  dialog, SLOT(setNewExample(QString)));
103 
104  dialog->setWindowTitle(description());
105  dialog->emitUpdate();
106  if (dialog->exec() != QDialog::Accepted) {
107  delete dialog;
108  return Q_NULLPTR;
109  }
110 
111  QStringList *list = new(std::nothrow) QStringList();
112  Q_ASSERT(list);
113  if (list) {
114  // user has pressed "OK"
115  QString pattern;
116 
117  QUrl url = dialog->selectedUrl();
118  if (url.isEmpty()) {
119  delete dialog;
120  delete list;
121  return Q_NULLPTR;
122  }
123  QString name = url.path();
124  QFileInfo path(name);
125 
126  // add the correct extension if necessary
127  if (!path.suffix().length()) {
128  QString ext = dialog->selectedExtension();
129  QStringList extensions = ext.split(_(" "));
130  ext = extensions.first();
131  name += ext.mid(1);
132  path = name;
133  url.setPath(name);
134  }
135 
136  name = Kwave::Parser::escape(name);
137  pattern = Kwave::Parser::escape(dialog->pattern());
138  int mode = static_cast<int>(dialog->numberingMode());
139  bool selection_only = (enable_selection_only) ?
140  dialog->selectionOnly() : m_selection_only;
141 
142  *list << name;
143  *list << pattern;
144  *list << QString::number(mode);
145  *list << QString::number(selection_only);
146 
147  emitCommand(_("plugin:execute(saveblocks,") +
148  name + _(",") + pattern + _(",") +
149  QString::number(mode) + _(",") +
150  QString::number(selection_only) + _(")")
151  );
152  }
153 
154  if (dialog) delete dialog;
155  return list;
156 }
157 
158 //***************************************************************************
160  const QStringList &list,
161  unsigned int max_entries) const
162 {
163  if (!max_entries || list.isEmpty()) return QString();
164 
165  QString retval;
166  unsigned int count = 0;
167 
168  foreach (const QString &entry, list) {
169  if (count == 0) // first entry
170  retval = _("<br><br>");
171  if (count < max_entries)
172  retval += entry + _("<br>");
173  else if (count == max_entries)
174  retval += i18n("...") + _("<br>");
175 
176  if (++count > max_entries)
177  break;
178  }
179 
180  return retval;
181 }
182 
183 //***************************************************************************
184 int Kwave::SaveBlocksPlugin::start(QStringList &params)
185 {
186  qDebug("SaveBlocksPlugin::start()");
187 
188  // interpret the parameters
189  int result = interpreteParameters(params);
190  if (result) return result;
191 
192  QString filename = m_url.path();
193  QFileInfo file(filename);
194  QString path = file.absolutePath();
195  QString ext = file.suffix();
196  QString base = findBase(filename, m_pattern);
197  QByteArray sep("/");
198 
199  // determine the selection settings
200  sample_index_t selection_left = 0;
201  sample_index_t selection_right = 0;
202  selection(Q_NULLPTR, &selection_left, &selection_right, false);
203 
204  bool selected_something = (selection_left != selection_right);
205  bool selected_all = ( (selection_left == 0) &&
206  ((selection_right + 1) >= signalLength()) );
207  bool enable_selection_only = selected_something && !selected_all;
208  bool selection_only = enable_selection_only && m_selection_only;
209  if (!selection_only) {
210  selection_left = 0;
211  selection_right = signalLength() - 1;
212  }
213 
214  // get the index range
215  scanBlocksToSave(base, selection_only);
216  unsigned int count = m_block_info.count();
217  unsigned int first = firstIndex(path, base, ext, m_pattern,
218  m_numbering_mode, count);
219 
220 // qDebug("m_url = '%s'", m_url.prettyURL().local8Bit().data());
221 // qDebug("m_pattern = '%s'", m_pattern.local8Bit().data());
222 // qDebug("m_numbering_mode = %d", (int)m_numbering_mode);
223 // qDebug("selection_only = %d", selection_only);
224 // qDebug("indices = %u...%u (count=%u)", first, first+count-1,count);
225 
226  // remember the original file info and determine the list of unsupported
227  // properties, we need that later to avoid that the signal manager
228  // complains on saving each and every block, again and again...
229  const Kwave::FileInfo orig_file_info(signalManager().metaData());
230  Kwave::FileInfo file_info(orig_file_info);
231  QList<Kwave::FileProperty> unsupported_properties;
232  {
233  QString mimetype = Kwave::CodecManager::mimeTypeOf(m_url);
234  Kwave::Encoder *encoder = Kwave::CodecManager::encoder(mimetype);
235  if (encoder) {
236  unsupported_properties = encoder->unsupportedProperties(
237  file_info.properties().keys());
238  delete encoder;
239  }
240  }
241 
242  // iterate over all blocks to check for overwritten files and missing dirs
243  QStringList overwritten_files;
244  QStringList missing_dirs;
245  for (unsigned int i = first; i < (first + count); i++) {
246  QString name = createFileName(base, ext, m_pattern, i, count,
247  first + count - 1);
248  QString display_name = Kwave::Parser::unescape(name);
249 
250  // split the name into directory and file name
251  name = QString::fromLatin1(QUrl::toPercentEncoding(display_name, sep));
252  QUrl url = m_url.adjusted(QUrl::RemoveFilename);
253  url.setPath(url.path(QUrl::FullyEncoded) + name, QUrl::StrictMode);
254 
255  QString p = url.path();
256  QFileInfo fi(p);
257 
258  // check for potentially overwritten file
259  if (fi.exists())
260  overwritten_files += Kwave::Parser::unescape(display_name);
261 
262  // check for missing subdirectory
263  if (!fi.dir().exists()) {
264  QString missing_dir = fi.absolutePath();
265  if (!missing_dirs.contains(missing_dir))
266  missing_dirs += missing_dir;
267  }
268  }
269 
270  // inform about overwritten files
271  if (!overwritten_files.isEmpty()) {
272  // ask the user for confirmation if he really wants to overwrite...
274  _("<html>") +
275  i18n("This would overwrite the following file(s): %1" \
276  "Do you really want to continue?",
277  createDisplayList(overwritten_files, 5)) +
278  _("</html>") ) != KMessageBox::Yes)
279  {
280  return -1;
281  }
282  }
283 
284  // handle missing directories
285  if (!missing_dirs.isEmpty()) {
286  // ask the user if he wants to continue and create the directory
288  i18n("The following directories do not exist: %1"
289  "Do you want to create them and continue?",
290  createDisplayList(missing_dirs, 5)),
291  QString(),
292  QString(),
293  QString(),
294  _("saveblocks_create_missing_dirs")
295  ) != KMessageBox::Continue)
296  {
297  return -1;
298  }
299 
300  // create all missing directories
301  QUrl base_url = m_url.adjusted(QUrl::RemoveFilename);
302  foreach (const QString &missing, missing_dirs) {
303  QUrl url(base_url);
304  url.setPath(
305  base_url.path(QUrl::FullyEncoded) +
306  QString::fromLatin1(QUrl::toPercentEncoding(missing)),
307  QUrl::StrictMode
308  );
309  QString p = url.path();
310  QDir dir;
311  if (!dir.mkpath(p))
312  qWarning("creating path '%s' failed", DBG(p));
313  }
314  }
315 
316  // save the current selection, we have to restore it afterwards!
317  sample_index_t saved_selection_left = 0;
318  sample_index_t saved_selection_right = 0;
319  selection(Q_NULLPTR, &saved_selection_left, &saved_selection_right, false);
320 
321  // now we can loop over all blocks and save them
322  sample_index_t block_start;
323  sample_index_t block_end = 0;
324  Kwave::LabelList labels(signalManager().metaData());
325  Kwave::LabelListIterator it(labels);
326  Kwave::Label label = it.hasNext() ? it.next() : Kwave::Label();
327 
328  for (unsigned int index = first;;) {
329  block_start = block_end;
330  block_end = (label.isNull()) ? signalLength() : label.pos();
331 
332  if ((selection_left < block_end) && (selection_right > block_start)) {
333  // found a block to save...
334  Q_ASSERT(index < first + count);
335 
336  sample_index_t left = block_start;
337  sample_index_t right = block_end - 1;
338  if (left < selection_left) left = selection_left;
339  if (right > selection_right) right = selection_right;
340  Q_ASSERT(right > left);
341  if (right <= left) break; // zero-length ?
342 
343  // select the range of samples
344  selectRange(left, right - left + 1);
345 
346  // determine the filename
347  QString name = createFileName(base, ext, m_pattern, index, count,
348  first + count - 1);
349  name = Kwave::Parser::unescape(name);
350  // use URL encoding for the filename
351  name = QString::fromLatin1(QUrl::toPercentEncoding(name, sep));
352  QUrl url = m_url.adjusted(QUrl::RemoveFilename);
353  url.setPath(url.path(QUrl::FullyEncoded) + name, QUrl::StrictMode);
354 
355  // enter the title of the block into the meta data if supported
356  if (!unsupported_properties.contains(INF_NAME)) {
357  QString title = orig_file_info.get(INF_NAME).toString();
358  int idx = index - first;
359  if ((idx >= 0) && (idx < m_block_info.count())) {
360  QString block_title = m_block_info[idx].m_title;
361  if (block_title.length())
362  title = title + _(", ") + block_title;
363  }
364  file_info.set(INF_NAME, QVariant(title));
366  Kwave::MetaDataList(file_info));
367  }
368 
369  qDebug("saving %9lu...%9lu -> '%s'",
370  static_cast<unsigned long int>(left),
371  static_cast<unsigned long int>(right),
372  DBG(url.toDisplayString()));
373  if (signalManager().save(url, true) < 0)
374  break;
375 
376  // if there were unsupported properties, the user might have been
377  // asked whether it is ok to continue or not. If he answered with
378  // "Cancel", we do not reach this point, otherwise we can continue
379  // and prevent any further annoying questions by removing all
380  // unsupported file info before the next run...
381  if ((index == first) && !unsupported_properties.isEmpty()) {
382  foreach (const Kwave::FileProperty &p, unsupported_properties) {
383  file_info.set(p, QVariant());
384  }
386  Kwave::MetaDataList(file_info));
387  }
388 
389  // increment the index for the next filename
390  index++;
391  }
392  if (label.isNull()) break;
393  label = (it.hasNext()) ? it.next() : Kwave::Label();
394  }
395 
396  // restore the original file info
398  Kwave::MetaDataList(orig_file_info));
399 
400  // restore the previous selection
401  selectRange(saved_selection_left,
402  (saved_selection_left != saved_selection_right) ?
403  (saved_selection_right - saved_selection_left + 1) : 0);
404 
405  return result;
406 }
407 
408 //***************************************************************************
410 {
411  bool ok;
412  QString param;
413 
414  // evaluate the parameter list
415  if (params.count() != 4) {
416  return -EINVAL;
417  }
418 
419  // the selected URL
420  m_url = QUrl::fromUserInput(Kwave::Parser::unescape(params[0]));
421  if (!m_url.isValid()) return -EINVAL;
422 
423  // filename pattern
424  m_pattern = Kwave::Parser::unescape(params[1]);
425  if (!m_pattern.length()) return -EINVAL;
426 
427  // numbering mode
428  param = params[2];
429  int mode = param.toInt(&ok);
430  Q_ASSERT(ok);
431  if (!ok) return -EINVAL;
432  if ((mode != CONTINUE) &&
433  (mode != START_AT_ONE)) return -EINVAL;
434  m_numbering_mode = static_cast<numbering_mode_t>(mode);
435 
436  // flag: save only the selection
437  param = params[3];
438  m_selection_only = (param.toUInt(&ok) != 0);
439  Q_ASSERT(ok);
440  if (!ok) return -EINVAL;
441 
442  return 0;
443 }
444 
445 //***************************************************************************
447  bool selection_only)
448 {
449  sample_index_t selection_left, selection_right;
450 
451  sample_index_t block_start;
452  sample_index_t block_end = 0;
453  QString block_title;
454  Kwave::LabelList labels(signalManager().metaData());
455  Kwave::LabelListIterator it(labels);
456  Kwave::Label label = (it.hasNext()) ? it.next() : Kwave::Label();
457 
458  if (selection_only) {
459  selection(Q_NULLPTR, &selection_left, &selection_right, true);
460  } else {
461  selection_left = 0;
462  selection_right = signalLength() - 1;
463  }
464 
465  // get the title of the whole file, in case that a block does not have
466  // an own title
467  FileInfo info(signalManager().metaData());
468  QString file_title = info.get(INF_NAME).toString();
469 
470  // fallback: if there is no INF_NAME either, fall back to the file
471  // name as last resort
472  if (!file_title.length()) file_title = base;
473 
474  m_block_info.clear();
475  QString prev_title;
476  for (;;) {
477  block_start = block_end;
478  block_end = (label.isNull()) ? signalLength() : label.pos();
479  block_title = prev_title;
480  prev_title = (label.isNull()) ? file_title : label.name();
481 
482  if ((block_end > selection_left) && (block_start <= selection_right)) {
483  BlockInfo block;
484  block.m_start = block_start;
485  block.m_length = block_end - block_start;
486  block.m_title = block_title;
487  if (!block.m_title.length()) block.m_title = file_title;
488  m_block_info.append(block);
489  }
490 
491  if (label.isNull()) break;
492  label = (it.hasNext()) ? it.next() : Kwave::Label();
493  }
494 }
495 
496 //***************************************************************************
497 QString Kwave::SaveBlocksPlugin::createFileName(const QString &base,
498  const QString &ext, const QString &pattern,
499  unsigned int index, int count, int total)
500 {
501  QString p = QRegExp::escape(pattern);
502  QString nr;
503 
504  // format the "index" parameter
505  QRegExp rx_nr(_("(\\\\\\[%(\\d*)nr\\\\\\])"), Qt::CaseInsensitive);
506  while (rx_nr.indexIn(p) >= 0) {
507  QString format = rx_nr.cap(1);
508  format = format.mid(2, format.length() - 6);
509  QString ex = _("(\\\\\\[") + format + _("nr\\\\\\])");
510  QRegExp rx(ex, Qt::CaseInsensitive);
511  format += _("u");
512  p.replace(rx, nr.sprintf(format.toLatin1(), index));
513  }
514 
515  // format the "count" parameter
516  QRegExp rx_count(_("(\\\\\\[%\\d*count\\\\\\])"), Qt::CaseInsensitive);
517  while (rx_count.indexIn(p) >= 0) {
518  if (count >= 0) {
519  QString format = rx_count.cap(1);
520  format = format.mid(2, format.length() - 9);
521  QString ex = _("(\\\\\\[") + format + _("count\\\\\\])");
522  QRegExp rx(ex, Qt::CaseInsensitive);
523  format += _("u");
524  p.replace(rx, nr.sprintf(format.toLatin1(), count));
525  } else {
526  p.replace(rx_count, _("(\\d+)"));
527  }
528  }
529 
530  // format the "total" parameter
531  QRegExp rx_total(_("(\\\\\\[%\\d*total\\\\\\])"), Qt::CaseInsensitive);
532  while (rx_total.indexIn(p) >= 0) {
533  if (total >= 0) {
534  QString format = rx_total.cap(1);
535  format = format.mid(2, format.length() - 9);
536  QString ex = _("(\\\\\\[") + format + _("total\\\\\\])");
537  QRegExp rx(ex, Qt::CaseInsensitive);
538  format += _("u");
539  p.replace(rx, nr.sprintf(format.toLatin1(), total));
540  } else {
541  p.replace(rx_total, _("(\\d+)"));
542  }
543  }
544 
545  // format the "filename" parameter
546  QRegExp rx_filename(_("\\\\\\[%filename\\\\\\]"), Qt::CaseInsensitive);
547  if (rx_filename.indexIn(p) >= 0) {
548  p.replace(rx_filename, QRegExp::escape(base));
549  }
550 
551  // support for file info
552  QRegExp rx_fileinfo(
553  _("\\\\\\[%(\\d*)fileinfo\\\\\\{([\\w\\s]+)\\\\\\}\\\\\\]"),
554  Qt::CaseInsensitive
555  );
556  Kwave::FileInfo info(signalManager().metaData());
557  while (rx_fileinfo.indexIn(p) >= 0) {
558  const QString format = rx_fileinfo.cap(1);
559  const QString id = rx_fileinfo.cap(2);
560  QString value;
561  FileProperty property = info.fromName(id);
562  if (property != Kwave::INF_UNKNOWN) {
563  QVariant val = info.get(property);
564  if (!val.isNull()) {
565  // we have a property value
566  value = val.toString();
567 
568  // check for format (desired minimum string length)
569  bool ok = false;
570  int len = format.toUInt(&ok);
571  if ((len > 0) && ok) {
572  Kwave::FileInfo::Flags flags = info.flags(property);
574  // numeric format, pad with leading zeros or spaces
575  QString pad = (format.startsWith(QLatin1Char('0'))) ?
576  _("0") : _(" ");
577  while (value.length() < len)
578  value = pad + value;
579  } else {
580  // string format, pad with trailing spaces
581  while (value.length() < len)
582  value = value + _(" ");
583  }
584  }
585  value = Kwave::Parser::escapeForFileName(value);
586  }
587  }
588 
589  QString ex(_("(\\\\\\[%") + format + _("fileinfo\\\\\\{") + id +
590  _("\\\\\\}\\\\\\])"));
591  QRegExp rx(ex, Qt::CaseInsensitive);
592  p.replace(rx, value);
593  }
594 
595  // format the "title" parameter
596  QRegExp rx_title(_("\\\\\\[%title\\\\\\]"), Qt::CaseInsensitive);
597  if (rx_title.indexIn(p) >= 0) {
598  QString title;
599  int idx = (index - 1) - (total - count);
600  if ((idx >= 0) && (idx < m_block_info.count()))
601  title = m_block_info[idx].m_title;
602  if (title.length()) {
603  title = Kwave::Parser::escapeForFileName(title);
604  p.replace(rx_title, title);
605  }
606  }
607 
608  if (ext.length()) p += _(".") + ext;
609 
610  // sanitize the filename/path, make sure that there are no spaces
611  // before and after all path separators
612  QString sep = _("/");
613  QRegExp rx_sep(_("\\s*") + sep + _("\\s*"));
614  p.replace(rx_sep, sep);
615 
616  return p;
617 }
618 
619 //***************************************************************************
620 unsigned int Kwave::SaveBlocksPlugin::firstIndex(const QString &path,
621  const QString &base, const QString &ext, const QString &pattern,
622  Kwave::SaveBlocksPlugin::numbering_mode_t mode, unsigned int count)
623 {
624  unsigned int first = 1;
625  switch (mode) {
626  case START_AT_ONE:
627  first = 1;
628  break;
629  case CONTINUE: {
630  QDir dir(path, _("*"));
631  QStringList files;
632  files = dir.entryList();
633  for (unsigned int i = first; i < (first + count); i++) {
634  QString name = createFileName(base, ext, pattern, i, -1, -1);
635  QRegExp rx(_("^(") + name + _(")$"),
636  Qt::CaseInsensitive);
637  QStringList matches = files.filter(rx);
638  if (matches.count() > 0) first = i + 1;
639  }
640  break;
641  }
642  }
643 
644  return first;
645 }
646 
647 //***************************************************************************
648 QString Kwave::SaveBlocksPlugin::findBase(const QString &filename,
649  const QString &pattern)
650 {
651  QFileInfo file(filename);
652  QString name = file.fileName();
653  QString base = file.completeBaseName();
654  QString ext = file.suffix();
655 
656  // convert the pattern into a regular expression in order to check if
657  // the current name already is produced by the current pattern
658  // \[%[0-9]?nr\] -> \d+
659  // \[%[0-9]?count\] -> \d+
660  // \[%[0-9]?total\] -> \d+
661  // \[%filename\] -> base
662  // \[%fileinfo\] -> .
663  // \[%title\] -> .
664  QRegExp rx_nr(_("\\\\\\[%\\d*nr\\\\\\]"), Qt::CaseInsensitive);
665  QRegExp rx_count(_("\\\\\\[%\\d*count\\\\\\]"), Qt::CaseInsensitive);
666  QRegExp rx_total(_("\\\\\\[%\\d*total\\\\\\]"), Qt::CaseInsensitive);
667  QRegExp rx_filename(_("\\\\\\[%filename\\\\\\]"), Qt::CaseInsensitive);
668  QRegExp rx_fileinfo(_("\\\\\\[%fileinfo\\\\\\]"), Qt::CaseInsensitive);
669  QRegExp rx_title(_("\\\\\\[%title\\\\\\]"), Qt::CaseInsensitive);
670 
671  QString p = QRegExp::escape(pattern);
672  int idx_nr = rx_nr.indexIn(p);
673  int idx_count = rx_count.indexIn(p);
674  int idx_total = rx_total.indexIn(p);
675  int idx_filename = rx_filename.indexIn(p);
676  int idx_fileinfo = rx_fileinfo.indexIn(p);
677  int idx_title = rx_fileinfo.indexIn(p);
678  p.replace(rx_nr, _("(\\d+)"));
679  p.replace(rx_count, _("(\\d+)"));
680  p.replace(rx_total, _("(\\d+)"));
681  p.replace(rx_filename, _("(.+)"));
682  p.replace(rx_fileinfo, _("(.+)"));
683  p.replace(rx_title, _("(.+)"));
684 
685  int max = 0;
686  for (int i = 0; i < pattern.length(); i++) {
687  if (idx_nr == max) max++;
688  if (idx_count == max) max++;
689  if (idx_total == max) max++;
690  if (idx_filename == max) max++;
691  if (idx_fileinfo == max) max++;
692  if (idx_title == max) max++;
693 
694  if (idx_nr > max) idx_nr--;
695  if (idx_count > max) idx_count--;
696  if (idx_total > max) idx_total--;
697  if (idx_filename > max) idx_filename--;
698  if (idx_fileinfo > max) idx_fileinfo--;
699  if (idx_title > max) idx_title--;
700  }
701 
702  if (ext.length()) p += _(".") + ext;
703  QRegExp rx_current(p, Qt::CaseInsensitive);
704  if (rx_current.indexIn(name) >= 0) {
705  // filename already produced by this pattern
706  base = rx_current.cap(idx_filename + 1);
707  }
708 
709  return base;
710 }
711 
712 //***************************************************************************
713 QString Kwave::SaveBlocksPlugin::firstFileName(const QString &filename,
714  const QString &pattern, Kwave::SaveBlocksPlugin::numbering_mode_t mode,
715  bool selection_only)
716 {
717  QFileInfo file(filename);
718  QString path = file.absolutePath();
719  QString ext = file.suffix();
720  QString base = findBase(filename, pattern);
721 
722  // now we have a new name, base and extension
723  // -> find out the numbering, min/max etc...
724  scanBlocksToSave(base, selection_only);
725  unsigned int count = m_block_info.count();
726  unsigned int first = firstIndex(path, base, ext, pattern, mode, count);
727  unsigned int total = first + count - 1;
728 
729  // create the complete filename, including extension but without path
730  return createFileName(base, ext, pattern, first, count, total);
731 }
732 
733 //***************************************************************************
734 void Kwave::SaveBlocksPlugin::updateExample(const QString &filename,
735  const QString &pattern, Kwave::SaveBlocksPlugin::numbering_mode_t mode,
736  bool selection_only)
737 {
738  QString example = firstFileName(filename, pattern, mode, selection_only);
739  emit sigNewExample(Kwave::Parser::unescape(example));
740 }
741 
742 //***************************************************************************
743 #include "SaveBlocksPlugin.moc"
744 //***************************************************************************
745 //***************************************************************************
static QString encodingFilter()
void emitCommand(const QString &command)
Definition: Plugin.cpp:510
QString createFileName(const QString &base, const QString &ext, const QString &pattern, unsigned int index, int count, int total)
numbering_mode_t m_numbering_mode
QList< BlockInfo > m_block_info
Definition: App.h:33
QString findBase(const QString &filename, const QString &pattern)
virtual QStringList * setup(QStringList &previous_params) Q_DECL_OVERRIDE
void updateExample(const QString &filename, const QString &pattern, Kwave::SaveBlocksPlugin::numbering_mode_t mode, bool selection_only)
QWidget * parentWidget() const
Definition: Plugin.cpp:450
Kwave::MetaDataList & metaData()
QVariant get(FileProperty key) const
Definition: FileInfo.cpp:372
Kwave::SignalManager & signalManager()
Definition: Plugin.cpp:444
virtual QString name() const
Definition: Plugin.cpp:196
virtual sample_index_t pos() const
Definition: Label.cpp:56
quint64 sample_index_t
Definition: Sample.h:28
static QString mimeTypeOf(const QUrl &url)
bool connect(Kwave::StreamObject &source, const char *output, Kwave::StreamObject &sink, const char *input)
Definition: Connect.cpp:48
void set(FileProperty key, const QVariant &value)
Definition: FileInfo.cpp:363
QListIterator< Kwave::Label > LabelListIterator
Definition: LabelList.h:76
QString firstFileName(const QString &filename, const QString &pattern, numbering_mode_t mode, bool selection_only)
static QString unescape(const QString &text)
Definition: Parser.cpp:314
static QString escapeForFileName(const QString &text)
Definition: Parser.cpp:295
virtual QList< Kwave::FileProperty > unsupportedProperties(const QList< Kwave::FileProperty > &properties_to_check)
Definition: Encoder.cpp:27
const QMap< FileProperty, QVariant > properties() const
Definition: FileInfo.cpp:389
FileProperty fromName(const QString &name) const
Definition: FileInfo.h:241
virtual bool isNull() const
Definition: MetaData.cpp:69
virtual QString name() const
Definition: Label.cpp:74
QString createDisplayList(const QStringList &list, unsigned int max_entries) const
virtual ~SaveBlocksPlugin() Q_DECL_OVERRIDE
virtual void replace(const MetaDataList &list)
unsigned int firstIndex(const QString &path, const QString &base, const QString &ext, const QString &pattern, Kwave::SaveBlocksPlugin::numbering_mode_t mode, unsigned int count)
virtual sample_index_t signalLength()
Definition: Plugin.cpp:462
static int warningYesNo(QWidget *widget, QString message, QString caption=QString(), const QString buttonYes=QString(), const QString buttonNo=QString(), const QString &dontAskAgainName=QString())
Definition: MessageBox.cpp:93
QString signalName()
Definition: Plugin.cpp:456
int interpreteParameters(QStringList &params)
static int warningContinueCancel(QWidget *widget, QString message, QString caption=QString(), const QString buttonContinue=QString(), const QString buttonCancel=QString(), const QString &dontAskAgainName=QString())
Definition: MessageBox.cpp:115
virtual void selectRange(sample_index_t offset, sample_index_t length)
Definition: Plugin.cpp:504
static Kwave::Encoder * encoder(const QString &mimetype_name)
#define KWAVE_PLUGIN(name, class)
Definition: Plugin.h:54
Flags flags(FileProperty key) const
Definition: FileInfo.h:205
#define _(m)
Definition: memcpy.c:66
void sigNewExample(const QString &example)
#define DBG(qs)
Definition: String.h:55
static QString escape(const QString &text)
Definition: Parser.cpp:277
FileProperty
Definition: FileInfo.h:45
virtual QString description() const
Definition: Plugin.cpp:202
void scanBlocksToSave(const QString &base, bool selection_only)
virtual int start(QStringList &params) Q_DECL_OVERRIDE
virtual sample_index_t selection(QList< unsigned int > *tracks=Q_NULLPTR, sample_index_t *left=Q_NULLPTR, sample_index_t *right=Q_NULLPTR, bool expand_if_empty=false)
Definition: Plugin.cpp:480