tagtransactionmanager.cpp 5.99 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
/***************************************************************************
    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.                                   *
 *                                                                         *
 ***************************************************************************/

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

#include <qfileinfo.h>
23
#include <QDir>
24 25 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

#include "tagtransactionmanager.h"
#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) {
Laurent Montel's avatar
Laurent Montel committed
74
        kWarning(65432) << "Trying to change tag on null PlaylistItem.\n";
75 76 77 78 79 80 81 82 83 84 85 86 87
        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)
{
88 89
    Q_ASSERT(tag);

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

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

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

    m_list.clear();
    return result;
}

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

bool TagTransactionManager::undo()
{
Laurent Montel's avatar
Laurent Montel committed
113
    kDebug(65432) << "Undoing " << m_undoList.count() << " changes.\n";
114 115 116 117

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

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

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

    return result;
}

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

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

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

   return false;
}

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

    it = undo ? m_undoList.begin() : m_list.begin();
    end = undo ? m_undoList.end() : m_list.end();

    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();
186
            QString str = errorTag->artist() + " - " + errorTag->title();
187 188

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

            errorItems.append(str);
        }
193 194

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

    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())
204
        KMessageBox::errorList(static_cast<QWidget *>(parent()),
205 206 207 208 209 210 211 212 213 214
                i18n("The following files were unable to be changed."),
                errorItems,
                i18n("Error"));

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

#include "tagtransactionmanager.moc"

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