tagtransactionmanager.cpp 5.11 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
/**
 * Copyright (C) 2004 Michael Pyne <mpyne@kde.org>
 *
 * This program is free software; you can redistribute it and/or modify it under
 * the terms of the GNU General Public License as published by the Free Software
 * Foundation; either version 2 of the License, or (at your option) any later
 * version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
 * PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with
 * this program.  If not, see <http://www.gnu.org/licenses/>.
 */
16

17 18
#include "tagtransactionmanager.h"

19
#include <KMessageBox>
Michael Pyne's avatar
Michael Pyne committed
20
#include <KLocalizedString>
21

22 23
#include <QAction>
#include <QApplication>
24
#include <QFileInfo>
25
#include <QDir>
26
#include <QGlobalStatic>
27 28 29 30 31

#include "playlistitem.h"
#include "collectionlist.h"
#include "tag.h"
#include "actioncollection.h"
Michael Pyne's avatar
Michael Pyne committed
32
#include "juk_debug.h"
33 34 35

using ActionCollection::action;

36
Q_GLOBAL_STATIC(TagTransactionManager, g_tagManager)
37

38
TagTransactionManager *TagTransactionManager::instance()
39
{
40
    return g_tagManager;
41 42
}

43 44 45
TagTransactionAtom::TagTransactionAtom(PlaylistItem *item, Tag *tag)
    : m_item(item)
    , m_tag(tag)
46 47 48 49 50 51
{
}

void TagTransactionManager::changeTagOnItem(PlaylistItem *item, Tag *newTag)
{
    if(!item) {
Michael Pyne's avatar
Michael Pyne committed
52
        qCWarning(JUK_LOG) << "Trying to change tag on null PlaylistItem.\n";
53 54 55 56 57 58 59 60
        return;
    }

    // Save the CollectionListItem, as it is the most likely to survive long
    // enough for the commit().  I should probably intercept the item deleted
    // signals from CollectionList to ensure that the commit list and the
    // playlists stay in sync.

61
    m_list.emplace_back(item->collectionItem(), newTag);
62 63 64 65
}

Tag *TagTransactionManager::duplicateTag(const Tag *tag, const QString &fileName)
{
66 67
    Q_ASSERT(tag);

68
    QString name = fileName.isEmpty() ? tag->fileName() : fileName;
69
    Tag *newTag = new Tag(*tag);
70

71
    newTag->setFileName(name);
72 73 74 75 76
    return newTag;
}

bool TagTransactionManager::commit()
{
77
    m_undoList.clear();
78 79 80 81 82 83 84 85 86 87 88 89 90
    bool result = processChangeList();

    m_list.clear();
    return result;
}

void TagTransactionManager::forget()
{
    m_list.clear();
}

bool TagTransactionManager::undo()
{
91
    qCDebug(JUK_LOG) << "Undoing " << m_undoList.size() << " changes.\n";
92 93 94 95

    forget();  // Scrap our old changes (although the list should be empty
               // anyways.

96 97 98 99 100 101 102 103 104 105
    bool result = processChangeList(true);

    m_undoList.clear();
    action("edit_undo")->setEnabled(false);

    return result;
}

bool TagTransactionManager::renameFile(const QFileInfo &from, const QFileInfo &to) const
{
Tim Beaulen's avatar
Tim Beaulen committed
106
   if(!QFileInfo(to.path()).isWritable() || !from.exists())
107 108 109
       return false;

   if(!to.exists() ||
110
       KMessageBox::warningContinueCancel(
111 112
           static_cast<QWidget *>(parent()),
           i18n("This file already exists.\nDo you want to replace it?"),
Will Entriken's avatar
Will Entriken committed
113
           i18n("File Exists"),KGuiItem(i18n("Replace"))) == KMessageBox::Continue)
114
   {
Michael Pyne's avatar
Michael Pyne committed
115
       qCDebug(JUK_LOG) << "Renaming " << from.absoluteFilePath() << " to " << to.absoluteFilePath();
116
       QDir currentDir;
Tim Beaulen's avatar
Tim Beaulen committed
117
       return currentDir.rename(from.absoluteFilePath(), to.absoluteFilePath());
118 119 120 121 122 123 124
   }

   return false;
}

bool TagTransactionManager::processChangeList(bool undo)
{
125
    TagAlterationList::const_iterator it, end;
126 127
    QStringList errorItems;

128 129
    it = undo ? m_undoList.cbegin() : m_list.cbegin();
    end = undo ? m_undoList.cend() : m_list.cend();
130 131 132 133 134

    emit signalAboutToModifyTags();

    for(; it != end; ++it) {
        PlaylistItem *item = (*it).item();
135
        const Tag *tag = (*it).tag();
136 137 138 139 140 141 142 143 144 145 146 147

        QFileInfo newFile(tag->fileName());

        if(item->file().fileInfo().fileName() != newFile.fileName()) {
            if(!renameFile(item->file().fileInfo(), newFile)) {
                errorItems.append(item->text(1) + QString(" - ") + item->text(0));
                continue;
            }
        }

        if(tag->save()) {
            if(!undo)
148
                m_undoList.emplace_back(item, duplicateTag(item->file().tag()));
149 150 151

            item->file().setFile(tag->fileName());
            item->refreshFromDisk();
152
            //FIXME repaint
153
            //item->repaint();
154
            item->playlist()->playlistItemsChanged();
155 156 157 158
            item->playlist()->update();
        }
        else {
            Tag *errorTag = item->file().tag();
159
            QString str = errorTag->artist() + " - " + errorTag->title();
160 161

            if(errorTag->artist().isEmpty())
162
                str = errorTag->title();
163 164 165

            errorItems.append(str);
        }
166

167
        qApp->processEvents();
168 169 170
    }

    undo ? m_undoList.clear() : m_list.clear();
171
    if(!undo && !m_undoList.empty())
172 173 174 175 176
        action("edit_undo")->setEnabled(true);
    else
        action("edit_undo")->setEnabled(false);

    if(!errorItems.isEmpty())
177
        KMessageBox::errorList(static_cast<QWidget *>(parent()),
178 179 180 181 182 183 184 185
                i18n("The following files were unable to be changed."),
                errorItems,
                i18n("Error"));

    emit signalDoneModifyingTags();
    return errorItems.isEmpty();
}

186
// vim: set et sw=4 tw=0 sta: