tagtransactionmanager.cpp 6 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
/***************************************************************************
    begin                : Wed Sep 22 2004
    copyright            : (C) 2004 by Michael Pyne
    email                : michael.pyne@kdemail.net
***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   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.                                   *
 *                                                                         *
 ***************************************************************************/

16 17
#include "tagtransactionmanager.h"

18 19 20 21
#include <kdebug.h>
#include <klocale.h>
#include <kmessagebox.h>
#include <kaction.h>
22
#include <kapplication.h>
23

24
#include <QFileInfo>
25
#include <QDir>
26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74

#include "playlistitem.h"
#include "collectionlist.h"
#include "tag.h"
#include "actioncollection.h"

using ActionCollection::action;

TagTransactionManager *TagTransactionManager::m_manager = 0;

TagTransactionAtom::TagTransactionAtom() : m_item(0), m_tag(0)
{
    action("edit_undo")->setEnabled(false);
}

TagTransactionAtom::TagTransactionAtom(const TagTransactionAtom &other) :
    m_item(other.m_item), m_tag(other.m_tag)
{
    other.m_tag = 0; // Only allow one owner
}

TagTransactionAtom::TagTransactionAtom(PlaylistItem *item, Tag *tag) :
    m_item(item), m_tag(tag)
{
}

TagTransactionAtom::~TagTransactionAtom()
{
    delete m_tag;
}

TagTransactionAtom &TagTransactionAtom::operator=(const TagTransactionAtom &other)
{
    m_item = other.m_item;
    m_tag = other.m_tag;

    other.m_tag = 0; // Only allow one owner

    return *this;
}

TagTransactionManager *TagTransactionManager::instance()
{
    return m_manager;
}

void TagTransactionManager::changeTagOnItem(PlaylistItem *item, Tag *newTag)
{
    if(!item) {
75
        kWarning() << "Trying to change tag on null PlaylistItem.\n";
76 77 78 79 80 81 82 83 84 85 86 87 88
        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.

    m_list.append(TagTransactionAtom(item->collectionItem(), newTag));
}

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

91
    QString name = fileName.isEmpty() ? tag->fileName() : fileName;
92
    Tag *newTag = new Tag(*tag);
93

94
    newTag->setFileName(name);
95 96 97 98 99
    return newTag;
}

bool TagTransactionManager::commit()
{
100
    m_undoList.clear();
101 102 103 104 105 106 107 108 109 110 111 112 113
    bool result = processChangeList();

    m_list.clear();
    return result;
}

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

bool TagTransactionManager::undo()
{
114
    kDebug() << "Undoing " << m_undoList.count() << " changes.\n";
115 116 117 118

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

119 120 121 122 123 124 125 126
    bool result = processChangeList(true);

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

    return result;
}

Tim Beaulen's avatar
Tim Beaulen committed
127
TagTransactionManager::TagTransactionManager(QWidget *parent) : QObject(parent)
128
{
Laurent Montel's avatar
Laurent Montel committed
129
    setObjectName( QLatin1String("tagmanager" ));
130 131 132 133 134
    m_manager = this;
}

bool TagTransactionManager::renameFile(const QFileInfo &from, const QFileInfo &to) const
{
Tim Beaulen's avatar
Tim Beaulen committed
135
   if(!QFileInfo(to.path()).isWritable() || !from.exists())
136 137 138
       return false;

   if(!to.exists() ||
139
       KMessageBox::warningContinueCancel(
140 141
           static_cast<QWidget *>(parent()),
           i18n("This file already exists.\nDo you want to replace it?"),
Will Entriken's avatar
Will Entriken committed
142
           i18n("File Exists"),KGuiItem(i18n("Replace"))) == KMessageBox::Continue)
143
   {
144
       kDebug() << "Renaming " << from.absoluteFilePath() << " to " << to.absoluteFilePath();
145
       QDir currentDir;
Tim Beaulen's avatar
Tim Beaulen committed
146
       return currentDir.rename(from.absoluteFilePath(), to.absoluteFilePath());
147 148 149 150 151 152 153 154 155 156
   }

   return false;
}

bool TagTransactionManager::processChangeList(bool undo)
{
    TagAlterationList::ConstIterator it, end;
    QStringList errorItems;

Laurent Montel's avatar
Laurent Montel committed
157 158
    it = undo ? m_undoList.constBegin() : m_list.constBegin();
    end = undo ? m_undoList.constEnd() : m_list.constEnd();
159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186

    emit signalAboutToModifyTags();

    for(; it != end; ++it) {
        PlaylistItem *item = (*it).item();
        Tag *tag = (*it).tag();

        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)
                m_undoList.append(TagTransactionAtom(item, duplicateTag(item->file().tag())));

            item->file().setFile(tag->fileName());
            item->refreshFromDisk();
            item->repaint();
            item->playlist()->dataChanged();
            item->playlist()->update();
        }
        else {
            Tag *errorTag = item->file().tag();
187
            QString str = errorTag->artist() + " - " + errorTag->title();
188 189

            if(errorTag->artist().isEmpty())
190
                str = errorTag->title();
191 192 193

            errorItems.append(str);
        }
194 195

        kapp->processEvents();
196 197 198 199 200 201 202 203 204
    }

    undo ? m_undoList.clear() : m_list.clear();
    if(!undo && !m_undoList.isEmpty())
        action("edit_undo")->setEnabled(true);
    else
        action("edit_undo")->setEnabled(false);

    if(!errorItems.isEmpty())
205
        KMessageBox::errorList(static_cast<QWidget *>(parent()),
206 207 208 209 210 211 212 213 214 215
                i18n("The following files were unable to be changed."),
                errorItems,
                i18n("Error"));

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

#include "tagtransactionmanager.moc"

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