Commit 0256d99d authored by Urs Fleisch's avatar Urs Fleisch
Browse files

all frames can be used for user commands, tags from file name, file name from ...

all frames can be used for user commands, tags from file name, file name from  tags, copy, rename directory; removed StandardTags
parent 2d392d83
......@@ -4,7 +4,7 @@ if (HAVE_TAGLIB)
set(TAGLIBEXT_LIBRARIES taglibext)
endif (HAVE_TAGLIB)
set(kid3_SRCS filelist.cpp filelistitem.cpp frame.cpp framelist.cpp frametable.cpp genres.cpp id3form.cpp kid3.cpp main.cpp m4afile.cpp mp3file.cpp standardtags.cpp configdialog.cpp exportdialog.cpp formatconfig.cpp formatbox.cpp importdialog.cpp importselector.cpp importparser.cpp generalconfig.cpp importconfig.cpp miscconfig.cpp freedbdialog.cpp freedbconfig.cpp freedbclient.cpp rendirdialog.cpp dirlist.cpp taggedfile.cpp musicbrainzdialog.cpp musicbrainzconfig.cpp musicbrainzclient.cpp numbertracksdialog.cpp oggfile.cpp vcedit.c flacfile.cpp commandstable.cpp taglibfile.cpp importsourceconfig.cpp importsourcedialog.cpp importsourceclient.cpp discogsdialog.cpp discogsclient.cpp discogsconfig.cpp musicbrainzreleasedialog.cpp musicbrainzreleaseclient.cpp externalprocess.cpp importtrackdata.cpp stringlistedit.cpp tracktypedialog.cpp tracktypeclient.cpp filterconfig.cpp filterdialog.cpp filefilter.cpp expressionparser.cpp pictureframe.cpp formatreplacer.cpp)
set(kid3_SRCS filelist.cpp filelistitem.cpp frame.cpp framelist.cpp frametable.cpp genres.cpp id3form.cpp kid3.cpp main.cpp m4afile.cpp mp3file.cpp configdialog.cpp exportdialog.cpp formatconfig.cpp formatbox.cpp importdialog.cpp importselector.cpp importparser.cpp generalconfig.cpp importconfig.cpp miscconfig.cpp freedbdialog.cpp freedbconfig.cpp freedbclient.cpp rendirdialog.cpp dirlist.cpp taggedfile.cpp musicbrainzdialog.cpp musicbrainzconfig.cpp musicbrainzclient.cpp numbertracksdialog.cpp oggfile.cpp vcedit.c flacfile.cpp commandstable.cpp taglibfile.cpp importsourceconfig.cpp importsourcedialog.cpp importsourceclient.cpp discogsdialog.cpp discogsclient.cpp discogsconfig.cpp musicbrainzreleasedialog.cpp musicbrainzreleaseclient.cpp externalprocess.cpp importtrackdata.cpp stringlistedit.cpp tracktypedialog.cpp tracktypeclient.cpp filterconfig.cpp filterdialog.cpp filefilter.cpp expressionparser.cpp pictureframe.cpp formatreplacer.cpp)
if (HAVE_QTDBUS)
set(kid3_SRCS ${kid3_SRCS} scriptinterface.cpp)
......
......@@ -28,14 +28,14 @@ kid3_LDADD += taglibext/libtaglibext.la
endif
# which sources should be compiled for kid3
kid3_SOURCES = filelist.cpp filelistitem.cpp frame.cpp framelist.cpp frametable.cpp genres.cpp id3form.cpp kid3.cpp main.cpp m4afile.cpp mp3file.cpp standardtags.cpp configdialog.cpp exportdialog.cpp formatconfig.cpp formatbox.cpp importdialog.cpp importselector.cpp importparser.cpp generalconfig.cpp importconfig.cpp miscconfig.cpp freedbdialog.cpp freedbconfig.cpp freedbclient.cpp rendirdialog.cpp dirlist.cpp taggedfile.cpp musicbrainzdialog.cpp musicbrainzconfig.cpp musicbrainzclient.cpp numbertracksdialog.cpp oggfile.cpp vcedit.c flacfile.cpp commandstable.cpp taglibfile.cpp importsourceconfig.cpp importsourcedialog.cpp importsourceclient.cpp discogsdialog.cpp discogsclient.cpp discogsconfig.cpp musicbrainzreleasedialog.cpp musicbrainzreleaseclient.cpp externalprocess.cpp importtrackdata.cpp stringlistedit.cpp tracktypedialog.cpp tracktypeclient.cpp scriptinterface.cpp filterconfig.cpp filterdialog.cpp filefilter.cpp expressionparser.cpp pictureframe.cpp formatreplacer.cpp
kid3_SOURCES = filelist.cpp filelistitem.cpp frame.cpp framelist.cpp frametable.cpp genres.cpp id3form.cpp kid3.cpp main.cpp m4afile.cpp mp3file.cpp configdialog.cpp exportdialog.cpp formatconfig.cpp formatbox.cpp importdialog.cpp importselector.cpp importparser.cpp generalconfig.cpp importconfig.cpp miscconfig.cpp freedbdialog.cpp freedbconfig.cpp freedbclient.cpp rendirdialog.cpp dirlist.cpp taggedfile.cpp musicbrainzdialog.cpp musicbrainzconfig.cpp musicbrainzclient.cpp numbertracksdialog.cpp oggfile.cpp vcedit.c flacfile.cpp commandstable.cpp taglibfile.cpp importsourceconfig.cpp importsourcedialog.cpp importsourceclient.cpp discogsdialog.cpp discogsclient.cpp discogsconfig.cpp musicbrainzreleasedialog.cpp musicbrainzreleaseclient.cpp externalprocess.cpp importtrackdata.cpp stringlistedit.cpp tracktypedialog.cpp tracktypeclient.cpp scriptinterface.cpp filterconfig.cpp filterdialog.cpp filefilter.cpp expressionparser.cpp pictureframe.cpp formatreplacer.cpp
# these headers are automatically built
BUILT_SOURCES =
CLEANFILES = allsys.h allsys.h.gch
# these are the headers for your project that won't be installed
noinst_HEADERS = configdialog.h exportdialog.h filelist.h filelistitem.h formatbox.h formatconfig.h frame.h framelist.h frametable.h freedbclient.h freedbconfig.h freedbdialog.h generalconfig.h genres.h id3form.h importconfig.h importdialog.h importparser.h importselector.h kid3.h miscconfig.h m4afile.h mp3file.h rendirdialog.h standardtags.h dirlist.h taggedfile.h musicbrainzclient.h musicbrainzconfig.h musicbrainzdialog.h numbertracksdialog.h oggfile.hpp vcedit.h flacfile.hpp commandstable.h taglibfile.h importsourceconfig.h importsourcedialog.h importsourceclient.h discogsdialog.h discogsclient.h discogsconfig.h musicbrainzreleasedialog.h musicbrainzreleaseclient.h qtcompatmac.h dirinfo.h externalprocess.h stringlistedit.h tracktypedialog.h tracktypeclient.h scriptinterface.h filterconfig.h filterdialog.h filefilter.h expressionparser.h pictureframe.h formatreplacer.h
noinst_HEADERS = configdialog.h exportdialog.h filelist.h filelistitem.h formatbox.h formatconfig.h frame.h framelist.h frametable.h freedbclient.h freedbconfig.h freedbdialog.h generalconfig.h genres.h id3form.h importconfig.h importdialog.h importparser.h importselector.h kid3.h miscconfig.h m4afile.h mp3file.h rendirdialog.h dirlist.h taggedfile.h musicbrainzclient.h musicbrainzconfig.h musicbrainzdialog.h numbertracksdialog.h oggfile.hpp vcedit.h flacfile.hpp commandstable.h taglibfile.h importsourceconfig.h importsourcedialog.h importsourceclient.h discogsdialog.h discogsclient.h discogsconfig.h musicbrainzreleasedialog.h musicbrainzreleaseclient.h qtcompatmac.h dirinfo.h externalprocess.h stringlistedit.h tracktypedialog.h tracktypeclient.h scriptinterface.h filterconfig.h filterdialog.h filefilter.h expressionparser.h pictureframe.h formatreplacer.h
# additional files in distribution
EXTRA_DIST = kid3.desktop kid3ui.rc hi16-app-kid3.png hi32-app-kid3.png hi48-app-kid3.png hisc-app-kid3.svgz de_qt.po ru_qt.po es_qt.po fr_qt.po
......
......@@ -63,6 +63,202 @@
#include "taglibfile.h"
#endif
/**
* Replaces context command format codes in a string.
*/
class CommandFormatReplacer : public FrameFormatReplacer {
public:
/**
* Constructor.
*
* @param frames frame collection
* @param str string with format codes
* @param files file list
* @param isDir true if directory
*/
explicit CommandFormatReplacer(
const FrameCollection& frames, const QString& str,
const QStringList& files, bool isDir);
/**
* Destructor.
*/
virtual ~CommandFormatReplacer();
/**
* Get help text for supported format codes.
*
* @param onlyRows if true only the tr elements are returned,
* not the surrounding table
*
* @return help text.
*/
static QString getToolTip(bool onlyRows = false);
protected:
/**
* Replace a format code (one character %c or multiple characters %{chars}).
* Supported format fields:
* Those supported by FrameFormatReplacer::getReplacement()
* %f %{file} filename
* %d %{directory} directory name
* %b %{browser} the web browser set in the configuration
*
* @param code format code
*
* @return replacement string,
* QString::null if code not found.
*/
virtual QString getReplacement(const QString& code) const;
private:
const QStringList& m_files;
const bool m_isDir;
};
/**
* Constructor.
*
* @param frames frame collection
* @param str string with format codes
* @param files file list
* @param isDir true if directory
*/
CommandFormatReplacer::CommandFormatReplacer(
const FrameCollection& frames, const QString& str,
const QStringList& files, bool isDir) :
FrameFormatReplacer(frames, str), m_files(files), m_isDir(isDir) {}
/**
* Destructor.
*/
CommandFormatReplacer::~CommandFormatReplacer() {}
/**
* Replace a format code (one character %c or multiple characters %{chars}).
* Supported format fields:
* Those supported by FrameFormatReplacer::getReplacement()
* %f %{file} filename
* %d %{directory} directory name
* %b %{browser} the web browser set in the configuration
*
* @param code format code
*
* @return replacement string,
* QString::null if code not found.
*/
QString CommandFormatReplacer::getReplacement(const QString& code) const
{
QString result = FrameFormatReplacer::getReplacement(code);
if (result.isNull()) {
QString name;
if (code.length() == 1) {
static const struct {
char shortCode;
const char* longCode;
} shortToLong[] = {
{ 'f', "file" },
{ 'd', "directory" },
{ 'b', "browser" }
};
#if QT_VERSION >= 0x040000
const char c = code[0].toLatin1();
#else
const char c = code[0].latin1();
#endif
for (unsigned i = 0; i < sizeof(shortToLong) / sizeof(shortToLong[0]); ++i) {
if (shortToLong[i].shortCode == c) {
name = shortToLong[i].longCode;
break;
}
}
} else if (code.length() > 1) {
name = code;
}
if (!name.isNull()) {
if (name == "file") {
result = m_files.front();
} else if (name == "directory") {
result = m_files.front();
if (!m_isDir) {
int sepPos = result.QCM_lastIndexOf('/');
if (sepPos < 0) {
sepPos = result.QCM_lastIndexOf(QDir::separator());
}
if (sepPos >= 0) {
result.truncate(sepPos);
}
}
} else if (name == "browser") {
result = Kid3App::s_miscCfg.m_browser;
} else if (name == "url") {
if (!m_files.empty()) {
QUrl url;
url.QCM_setScheme("file");
url.QCM_setPath(m_files.front());
result = url.toString(
#if QT_VERSION < 0x040000
true
#endif
);
}
}
}
}
return result;
}
/**
* Get help text for supported format codes.
*
* @param onlyRows if true only the tr elements are returned,
* not the surrounding table
*
* @return help text.
*/
QString CommandFormatReplacer::getToolTip(bool onlyRows)
{
QString str;
if (!onlyRows) str += "<table>\n";
str += FrameFormatReplacer::getToolTip(true);
str += "<tr><td>%f</td><td>%{file}</td><td>";
str += QCM_translate("Filename");
str += "</td></tr>\n";
str += "<tr><td>%F</td><td>%{files}</td><td>";
str += QCM_translate(I18N_NOOP("Filenames"));
str += "</td></tr>\n";
str += "<tr><td>%uf</td><td>%{url}</td><td>";
str += QCM_translate("URL");
str += "</td></tr>\n";
str += "<tr><td>%uF</td><td>%{urls}</td><td>";
str += QCM_translate(I18N_NOOP("URLs"));
str += "</td></tr>\n";
str += "<tr><td>%d</td><td>%{directory}</td><td>";
str += QCM_translate(I18N_NOOP("Directory name"));
str += "</td></tr>\n";
str += "<tr><td>%b</td><td>%{browser}</td><td>";
str += QCM_translate("Browser");
str += "</td></tr>\n";
str += "<tr><td>%ua...</td><td>%u{artist}...</td><td>";
str += QCM_translate(I18N_NOOP("Encode as URL"));
str += "</td></tr>\n";
if (!onlyRows) str += "</table>\n";
return str;
}
/**
* Constructor.
* @param parent parent widget
......@@ -657,7 +853,7 @@ void FileList::contextMenu(
/**
* Format a string list from the selected files.
* Supported format fields:
* Those supported by StandardTags::formatString(),
* Those supported by FrameFormatReplacer::getReplacement(),
* when prefixed with u, encoded as URL
* %f filename
* %F list of files
......@@ -698,6 +894,7 @@ QStringList FileList::formatStringList(const QStringList& format)
firstSelectedItem = firstInDir();
}
FrameCollection frames;
QStringList fmt;
for (QStringList::const_iterator it = format.begin();
it != format.end();
......@@ -719,54 +916,18 @@ QStringList FileList::formatStringList(const QStringList& format)
fmt.push_back(url.toString());
}
} else {
const int numTagCodes = 3;
const QChar tagCode[numTagCodes] = { 'f', 'd', 'b' };
const QStringList tagLongCodes =
(QStringList() << "file" << "directory" << "browser");
QString tagStr[numTagCodes];
if (!files.empty()) {
tagStr[0] = files.front();
tagStr[1] = tagStr[0];
tagStr[2] = Kid3App::s_miscCfg.m_browser;
if (!dirInfo) {
int sepPos = tagStr[1].QCM_lastIndexOf('/');
if (sepPos < 0) {
sepPos = tagStr[1].QCM_lastIndexOf(QDir::separator());
}
if (sepPos >= 0) {
tagStr[1].truncate(sepPos);
}
}
}
QString str = StandardTags::replacePercentCodes(
*it, tagCode, tagLongCodes, tagStr, numTagCodes);
int ufLen = 0;
int ufPos = str.QCM_indexOf("%uf");
if (ufPos != -1) {
ufLen = 3;
} else {
ufPos = str.QCM_indexOf("%{url}");
if (ufPos != -1) {
ufLen = 6;
}
}
if (ufPos != -1 && !files.empty()) {
QUrl url;
url.QCM_setScheme("file");
url.QCM_setPath(files.front());
str.replace(ufPos, ufLen, url.toString());
}
if (firstSelectedItem) {
// use merged tags 1 and 2 to format string
StandardTags st1, st2;
firstSelectedItem->getFile()->getStandardTagsV1(&st1);
firstSelectedItem->getFile()->getStandardTagsV2(&st2);
st2.merge(st1);
str = st2.formatString(str, StandardTags::FSF_SupportUrlEncode);
FrameCollection frames1;
firstSelectedItem->getFile()->getAllFramesV1(frames1);
firstSelectedItem->getFile()->getAllFramesV2(frames);
frames.merge(frames1);
}
fmt.push_back(str);
QString str(*it);
str.replace("%uf", "%{url}");
CommandFormatReplacer cfr(frames, str, files, dirInfo != 0);
cfr.replacePercentCodes(FrameFormatReplacer::FSF_SupportUrlEncode);
fmt.push_back(cfr.getString());
}
}
}
......@@ -783,40 +944,7 @@ QStringList FileList::formatStringList(const QStringList& format)
*/
QString FileList::getFormatToolTip(bool onlyRows)
{
QString str;
if (!onlyRows) str += "<table>\n";
str += StandardTags::getFormatToolTip(true);
str += "<tr><td>%f</td><td>%{file}</td><td>";
str += QCM_translate("Filename");
str += "</td></tr>\n";
str += "<tr><td>%F</td><td>%{files}</td><td>";
str += QCM_translate(I18N_NOOP("Filenames"));
str += "</td></tr>\n";
str += "<tr><td>%uf</td><td>%{url}</td><td>";
str += QCM_translate("URL");
str += "</td></tr>\n";
str += "<tr><td>%uF</td><td>%{urls}</td><td>";
str += QCM_translate(I18N_NOOP("URLs"));
str += "</td></tr>\n";
str += "<tr><td>%d</td><td>%{directory}</td><td>";
str += QCM_translate(I18N_NOOP("Directory name"));
str += "</td></tr>\n";
str += "<tr><td>%b</td><td>%{browser}</td><td>";
str += QCM_translate("Browser");
str += "</td></tr>\n";
str += "<tr><td>%ua...</td><td>%u{artist}...</td><td>";
str += QCM_translate(I18N_NOOP("Encode as URL"));
str += "</td></tr>\n";
if (!onlyRows) str += "</table>\n";
return str;
return CommandFormatReplacer::getToolTip(onlyRows);
}
/**
......
......@@ -271,7 +271,7 @@ private:
/**
* Format a string list from the selected files.
* Supported format fields:
* Those supported by StandardTags::formatString(),
* Those supported by FrameFormatReplacer::getReplacement(),
* when prefixed with u, encoded as URL
* %f filename
* %F list of files
......
......@@ -27,7 +27,6 @@
#include "flacfile.hpp"
#ifdef HAVE_FLAC
#include "standardtags.h"
#include "genres.h"
#include "dirinfo.h"
#include "pictureframe.h"
......
......@@ -34,7 +34,6 @@
#endif
#include "qtcompatmac.h"
#include "generalconfig.h"
#include "standardtags.h"
#include "formatconfig.h"
#include "frame.h"
......@@ -154,19 +153,6 @@ void FormatConfig::formatString(QString& str) const
}
}
/**
* Format title, artist and album using this configuration.
*
* @param st standard tags
*/
void FormatConfig::formatStandardTags(StandardTags& st) const
{
formatString(st.title);
formatString(st.artist);
formatString(st.album);
formatString(st.comment);
}
/**
* Format frames using this configuration.
*
......
......@@ -32,7 +32,6 @@
#include <qmap.h>
class QString;
class StandardTags;
class FrameCollection;
/**
......@@ -77,13 +76,6 @@ public:
*/
void formatString(QString& str) const;
/**
* Format title, artist and album using this configuration.
*
* @param st standard tags
*/
void formatStandardTags(StandardTags& st) const;
/**
* Format frames using this configuration.
*
......
......@@ -102,8 +102,12 @@ void FormatReplacer::replacePercentCodes(unsigned flags)
if (urlEncode) {
QCM_QUrl_encode(repl);
}
m_str.replace(pos, codeLen, repl);
pos += repl.length();
if (!repl.isNull() || codeLen > 2) {
m_str.replace(pos, codeLen, repl);
pos += repl.length();
} else {
++pos;
}
} else {
++pos;
}
......
......@@ -261,10 +261,11 @@ FrameCollection FrameCollection::copyEnabledFrames(const FrameFilter& flt) const
void FrameCollection::removeDisabledFrames(const FrameFilter& flt)
{
for (iterator it = begin();
it != end();
++it) {
it != end();) {
if (!flt.isEnabled(it->getType(), it->getName())) {
erase(it);
erase(it++);
} else {
++it;
}
}
}
......@@ -297,6 +298,23 @@ void FrameCollection::merge(const FrameCollection& frames)
}
}
/**
* Check if the standard tags are empty or inactive.
*
* @return true if empty or inactive.
*/
bool FrameCollection::isEmptyOrInactive() const
{
return
getTitle().isEmpty() &&
getArtist().isEmpty() &&
getAlbum().isEmpty() &&
getComment().isEmpty() &&
getYear() <= 0 &&
getTrack() <= 0 &&
getGenre().isEmpty();
}
/**
* Find a frame by name.
*
......@@ -389,40 +407,6 @@ void FrameCollection::setIntValue(Frame::Type type, int value)
}
}
/**
* Set standard tag fields.
*
* @param st standard tags
*/
void FrameCollection::setStandardTags(const StandardTags& st)
{
setTitle(st.title);
setArtist(st.artist);
setAlbum(st.album);
setComment(st.comment);
setGenre(st.genre);
setYear(st.year);
setTrack(st.track);
}
/**
* Get standard tag fields.
*
* @param st standard tags
*/
StandardTags FrameCollection::getStandardTags() const
{
StandardTags st;
st.title = getTitle();
st.artist = getArtist();
st.album = getAlbum();
st.comment = getComment();
st.genre = getGenre();
st.year = getYear();
st.track = getTrack();
return st;
}
/**
* Constructor.
......
......@@ -28,7 +28,6 @@
#define FRAME_H
#include "formatreplacer.h"
#include "standardtags.h"
#include <qstring.h>
#include <qvariant.h>
#if QT_VERSION >= 0x040000
......@@ -411,6 +410,13 @@ public:
*/
void merge(const FrameCollection& frames);
/**
* Check if the standard tags are empty or inactive.
*
* @return true if empty or inactive.
*/
bool isEmptyOrInactive() const;
/**
* Find a frame by name.
*
......@@ -456,20 +462,6 @@ public:
*/
void setIntValue(Frame::Type type, int value);
/**
* Set standard tag fields.
*
* @param st standard tags
*/
void setStandardTags(const StandardTags& st);
/**
* Get standard tag fields.
*
* @param st standard tags
*/
StandardTags getStandardTags() const;
/**
* Get artist.
*
......
......@@ -189,7 +189,7 @@ Id3Form::Id3Form(QWidget* parent)
m_formatComboBox = new QComboBox(filenameGroupBox);
m_formatComboBox->setEditable(true);
m_formatComboBox->setToolTip(StandardTags::getFormatToolTip());
m_formatComboBox->setToolTip(FrameFormatReplacer::getToolTip());
filenameGroupBoxLayout->addWidget(m_formatComboBox, 1, 1);
QPushButton* fnV2Button =
......@@ -319,7 +319,7 @@ Id3Form::Id3Form(QWidget* parent)
m_formatComboBox = new QComboBox(filenameGroupBox);
m_formatComboBox->setEditable(true);
QToolTip::add(m_formatComboBox, StandardTags::getFormatToolTip());
QToolTip::add(m_formatComboBox, FrameFormatReplacer::getToolTip());
filenameGroupBoxLayout->addWidget(m_formatComboBox, 2, 1);
QPushButton* fnV2Button =
......@@ -703,46 +703,6 @@ void Id3Form::dirSelected(
}
}
/**
* Get filter from ID3v1 check boxes.
*
* @return filter.
*/
StandardTagsFilter Id3Form::getFilterFromID3V1()
{
StandardTagsFilter flt;
FrameFilter frameFilter(m_framesV1Table->getEnabledFrameFilter());
flt.m_enableTitle = frameFilter.isEnabled(Frame::FT_Title);
flt.m_enableArtist = frameFilter.isEnabled(Frame::FT_Artist);
flt.m_enableAlbum = frameFilter.isEnabled(Frame::FT_Album);
flt.m_enableComment = frameFilter.isEnabled(Frame::FT_Comment);
flt.m_enableYear = frameFilter.isEnabled(Frame::FT_Date);
flt.m_enableTrack = frameFilter.isEnabled(Frame::FT_Track);
flt.m_enableGenre = frameFilter.isEnabled(Frame::FT_Genre);
flt.allFalseToAllTrue();
return flt;
}
/**
* Get filter from ID3v2 check boxes.
*
* @return filter.
*/
StandardTagsFilter Id3Form::getFilterFromID3V2()
{
StandardTagsFilter flt;
FrameFilter frameFilter(m_framesV2Table->getEnabledFrameFilter());
flt.m_enableTitle = frameFilter.isEnabled(Frame::FT_Title);
flt.m_enableArtist = frameFilter.isEnabled(Frame::FT_Artist);
flt.m_enableAlbum = frameFilter.isEnabled(Frame::FT_Album);
flt.m_enableComment = frameFilter.isEnabled(Frame::FT_Comment);
flt.m_enableYear = frameFilter.isEnabled(Frame::FT_Date);
flt.m_enableTrack = frameFilter.isEnabled(Frame::FT_Track);
flt.m_enableGenre = frameFilter.isEnabled(Frame::FT_Genre);
flt.allFalseToAllTrue();
return flt;