コード例 #1
0
QMimeData *NavTagItemModel::mimeData(const QModelIndexList &indexes) const
{
    QList<QStringList> tagPaths;
    foreach (const QModelIndex &index, indexes)
    {
        if (!index.isValid())
            continue;

        TagItem *tagItem = static_cast<TagItem *>(index.internalPointer());
        if (!tagItem)
            continue;

        tagPaths.push_back(tagItem->path());
    }

    if (tagPaths.isEmpty())
        return 0;

    QByteArray encodedData;
    QDataStream stream(&encodedData, QIODevice::WriteOnly);
    stream << tagPaths;

    QMimeData *mimeData = new QMimeData();
    mimeData->setData("qookmarks/tag-list", encodedData);
    return mimeData;
}
コード例 #2
0
ファイル: tagEditor.cpp プロジェクト: ivareske/TagEditor
void TagEditor::serialize(){

    QModelIndexList indexes = TreeWidget_->selectionModel()->selectedRows();
    qDebug()<<indexes.size();
    if(indexes.size()==0){
        QMessageBox msgBox;
        msgBox.setText("No files selected...");
        msgBox.exec();
        return;
    }

    bool ok;
    uint track = QInputDialog::getInt(this, "",tr("Starting index:"), 1, 0, 99999, 1, &ok);

    qDebug()<<ok;
    if(!ok){
        statusBar()->showMessage("Canceled by user", 8000);
        return;
    }

    QString log;
    TagLib::FileRef f;
    for(int i=0;i<indexes.size();i++){
        TagItem *item = TreeWidget_->tagItem(indexes[i].row()); // ((TagItem*)TreeWidget_->topLevelItem( indexes[i].row() ));
        QString fullfile = item->fileInfo().absoluteFilePath();
        /*
        f = TagLib::FileRef( fullfile.toStdString().c_str() );
        if( f.tag() ){
            f.tag()->setTrack( track );
            item->setTag( Global::Track, track );
            bool ok = f.save();
            if(!ok){
                log.append("\nCould not save tag for "+fullfile);
            }
        }else{
            log.append("\nCould not read tag for "+fullfile);
        }
        */
        item->setTrack(track);
        bool ok = item->saveTag();
        if(!ok){
            log.append("\nCould not save tag for "+fullfile);
        }
        track++;
    }

    statusBar()->showMessage("Finished serializing tracks", 8000);
    if(!log.isEmpty()){
        TextViewer t(log);
        t.exec();
    }
}
コード例 #3
0
bool NavTagItemModel::dropMimeData(const QMimeData *data,
        Qt::DropAction action, int /*row*/, int /*column*/,
        const QModelIndex &parent)
{
    TagItem *parentItem = static_cast<TagItem *>(parent.internalPointer());
    QStringList path = (parentItem ? parentItem->path() : QStringList());
    if (data->hasFormat("qookmarks/tag-list"))
        return dropMimeTagList(data, path);
    else if (data->hasFormat("qookmarks/bookmark-list"))
        return dropMimeBookmarkList(data, path, action);

    return false;
}
コード例 #4
0
/**
 * @brief slot: add a tag item to internal QMap and scene
 * @param tagId	id of the tag
 * @param color color of the tag
 * @return
 *      void
 */
void DLDMapScene::addTagItem (int tagId, QColor color)
{
	if (tags.contains(tagId))
		return ;
	TagItem * item = new TagItem ();
	item->setBrush (QBrush(color));
	item->setTagId (tagId);
	tags.insert (tagId, item);

	addItem (item);
	connect (item, SIGNAL (mouseEnterTag (int, int, int)), this, SIGNAL (mouseEnterTag (int, int, int)));
	connect (item, SIGNAL (mouseLeaveTag ()), this, SIGNAL (mouseLeaveTag ()));
	connect (item, SIGNAL (mouseMoveOverTag (int, int, int)), this, SIGNAL (mouseMoveOverTag (int, int, int)));
}
コード例 #5
0
QVariant NavTagItemModel::data(const QModelIndex &index, int role) const
{
    if (!index.isValid())
        return QVariant();

    TagItem *item = static_cast<TagItem *>(index.internalPointer());
    if (role == Qt::DisplayRole || role == Qt::ToolTipRole)
        if (index.column() == 0)
            return QString("%1 (%2)")
                    .arg(item->data().name())
                    .arg(bookmarkNotTrashedCount(item));

    return TagItemModel::data(index, role);
}
コード例 #6
0
ファイル: tagEditor.cpp プロジェクト: ivareske/TagEditor
/*
void TagEditor::removeFrames(){
    QModelIndexList indexes = TreeWidget_->selectionModel()->selectedRows();
    if(indexes.size()==0){
        QMessageBox msgBox;
        msgBox.setText("No files selected...");
        msgBox.exec();
        return;
    }

    QMessageBox msgBox;
    msgBox.setText("Removing frames/items");
    msgBox.setInformativeText("Are you sure you want to remove all frames/items from ID3v2/APE tags for the selected files?");
    msgBox.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel);
    msgBox.setDefaultButton(QMessageBox::Ok);
    int ret = msgBox.exec();
    if(ret==QMessageBox::Cancel){
        return;
    }

    QProgressDialog p("Removing frames...", "Cancel", 0, indexes.size(), this);
    p.setWindowModality(Qt::WindowModal);
    QString log;
    for(int i=0;i<indexes.size();i++){
        QString fullfile = ((TagItem*)TreeWidget_->topLevelItem( indexes[i].row() ))->fileInfo().absoluteFilePath();
        TagLib::MPEG::File f( fullfile.toStdString().c_str() );
        //TagLib::FileRef f = TagLib::FileRef( fullfile.toStdString().c_str() );
        qDebug()<<1;
        //TagLib::ID3v2::Tag *id3v2tag = f.ID3v2Tag();
        qDebug()<<1.1;
        if(f.ID3v2Tag()){
            TagLib::ID3v2::FrameList::ConstIterator it = f.ID3v2Tag()->frameList().begin();
            qDebug()<<1.2;
            int k=0;
            while ( f.ID3v2Tag()->frameList().size()>0 ) {
                TagLib::ID3v2::Frame *frame = *(f.ID3v2Tag()->frameList().begin());
                qDebug()<<"removing frame: "<<frame->toString().toCString();
                f.ID3v2Tag()->removeFrame(frame, true );
            }
            qDebug()<<1.3;
            if(k>0){
                log.append("Removed "+QString::number(k)+" frames from ID3v2 tag for "+fullfile);
            }
        }
        qDebug()<<2;
        TagLib::APE::Tag *ape = f.APETag();
        if(ape){
            int k=0;
            for(TagLib::APE::ItemListMap::ConstIterator it = ape->itemListMap().begin(); it != ape->itemListMap().end(); ++it){
                ape->removeItem( (*it).second.key() );
            }
            if(k>0){
                log.append("Removed "+QString::number(k)+" frames from APE tag for "+fullfile);
            }
        }
        qDebug()<<3;
        p.setValue(i);
        p.setLabelText("Removing frames/items from ID3v2/APE tags...\nFile "+QString::number(i)+" of "+QString::number(indexes.size()));
        if( p.wasCanceled() ){
            log.append("\n\nCanceled by user at "+fullfile);
            break;
        }
        if(!ape && !f.ID3v2Tag()){
            continue;
        }
        bool ok = f.save();
        qDebug()<<"saved file"<<ok;
        if(!ok){
            log.append("\nCould not save tag for "+fullfile);
        }
    }
    p.setValue(indexes.size());
    statusBar()->showMessage("Finished removing frames/items", 8000);
    if(!log.isEmpty()){
        TextViewer t(this, &log);
        t.resize(textViewerSize);
        t.exec();
        textViewerSize = t.size();
    }
}
*/
void TagEditor::rewriteTag(){

    QModelIndexList indexes = TreeWidget_->selectionModel()->selectedRows();
    if(indexes.size()==0){
        QMessageBox msgBox;
        msgBox.setText("No files selected...");
        msgBox.exec();
        return;
    }

    QProgressDialog p("Rewriting tags...", "Cancel", 0, indexes.size(), this);
    p.setWindowModality(Qt::WindowModal);
    QString log; QList<TagItem*> items;
    for(int i=0;i<indexes.size();i++){
        TagItem* item = TreeWidget_->tagItem(indexes[i].row());
        QString fullfile = item->fileInfo().absoluteFilePath();
        item->readTags();
        if( !item->tagOk() ){
            log.append("\nCould not read tag for "+fullfile);
            continue;
        }
        bool ok = item->saveTag();
        if(!ok){
            log.append("\nCould not save tag for "+fullfile);
        }
        p.setValue(i);
        p.setLabelText("Rewriting tags...\nFile "+QString::number(i)+" of "+QString::number(indexes.size()));
        if( p.wasCanceled() ){
            log.append("\n\nCanceled by user at "+fullfile);
            break;
        }
        items.append(item);
    }
    TreeWidget_->updateItems(items);
    p.setValue(indexes.size());
    statusBar()->showMessage("Finished rewriting tags", 8000);
    if(!log.isEmpty()){
        TextViewer t(log);
        t.exec();
    }
}
コード例 #7
0
ファイル: renameDialog.cpp プロジェクト: ivareske/TagEditor
void RenameDialog::rename(){

    QString tmpformat;
    if( replaceFormat.size()%2 != 0 ){
        QMessageBox msgBox;
        msgBox.setText("Replace format must be specified in comma-separated pairs...");
        msgBox.exec();
        return;
    }

    QString log;
    QProgressDialog p("Renaming files...", "Cancel", 0, tagItems.size(), this);
    for(int i=0;i<tagItems.size();i++){

        p.setValue(i);
        if( p.wasCanceled() ){
            break;
        }

        TagItem *item = tagItems[i];
        QFileInfo fi = item->fileInfo();
        tmpformat = Format->text();

        if( !item->tagIsRead() ){
            item->readTags();
        }

        if( !item->tagOk() ){
            log.append("\nCould not read tag for "+fi.absoluteFilePath());
            continue;
        }
        tmpformat.replace( "%artist%", item->artist() );
        tmpformat.replace( "%album%", item->album() );
        tmpformat.replace( "%title%", item->title() );
        tmpformat.replace( "%genre%", item->genre() );
        tmpformat.replace( "%track%", QString::number( item->track() ) );
        tmpformat.replace( "%year%", QString::number( item->year() ) );
        tmpformat.replace( "%comment%", item->comment() );
        tmpformat.replace( "%bitrate%", QString::number( item->bitRate() ) );
        tmpformat.replace( "%samplerate%", QString::number( item->sampleRate() ) );
        tmpformat.replace( "%length%", QString::number( item->length() ) );
        tmpformat.replace( "%channels%", QString::number( item->channels() ) );

        for(int i=0;i<replaceFormat.size();i=i+2){
            tmpformat.replace( replaceFormat[i], replaceFormat[i+1] );
        }

        bool formatok=true;
        for(int i=0;i<notAllowedCharacters.size();i++){
            if( tmpformat.contains(notAllowedCharacters[i]) ){
                log.append("\nCharacter "+notAllowedCharacters[i]+" is not allowed in filename and must be replaced.");
                formatok = false;
            }
        }
        if(!formatok){
            continue;
        }

        QString ext = fi.suffix();
        QString newname = fi.absolutePath()+"/"+tmpformat+"."+ext;
        //QString newnameShort = tmpformat+"."+ext;
        bool ok = QFile::rename( fi.absoluteFilePath(), newname );

        if(!ok){
            if(fi.absoluteFilePath()==newname){
                //log.append("\nCould not rename "+fi.absoluteFilePath()+" to "+newname);
            }else{
                log.append("\nCould not rename "+fi.absoluteFilePath()+" to "+newname);
            }
        }else{
            //update listWidgetItem with new name
            item->changeName( newname );
        }

    }
    p.setValue(tagItems.size());
    if(!log.isEmpty()){
        TextViewer t(log);
        t.exec();
    }

    accept();
}
コード例 #8
0
ファイル: tagEditor.cpp プロジェクト: ivareske/TagEditor
void TagEditor::searchOnline(){

    QModelIndexList indexes = TreeView->selectionModel()->selectedRows(0);

    if(indexes.size()==0){
        QMessageBox msgBox;
        msgBox.setText("No rows selected");
        msgBox.exec();
        return;
    }

    QModelIndex index = indexes[0];
    QFileSystemModel *m = (QFileSystemModel *)TreeView->model();
    bool isdir = m->isDir(index);

    QString query;
    QList<QFileInfo> info;
    QList<TagItem*> items;
    if(isdir){
        //folder/album
        QString folder = m->filePath(index);
        info = Global::getDirContent( folder, extensions, subfolders );
    }else{
        for(int i=0;i<indexes.size();i++){
            info.append( m->fileInfo( indexes[i] ) );
        }
    }
    if(info.size()==0){
        QMessageBox msgBox;
        msgBox.setText("Empty folder...");
        msgBox.exec();
        return;
    }

    for(int i=0;i<info.size();i++){
        items.append(new TagItem(info[i].absoluteFilePath()));
    }

    SearchDialog d( items, this );
    //d.setModal(false);
    d.exec();
    /*
	if( d.exec()>=0 ){
		//save settings anyway
		//settings = d.getSettings();
	}
	*/

    //delete tag data from these files if they exist in TreeWidget_, since the tag data now might get changed
    for(int i=0;i<TreeWidget_->topLevelItemCount();i++){
        if( info.size()==0 ){
            break;
        }
        TagItem *item = (TagItem*)TreeWidget_->topLevelItem(i);
        for(int j=0;j<info.size();j++){
            if( item->data(0,TreeWidget::FULLFILE)==info.at(j).absoluteFilePath() ){
                item->clearTags();
                info.removeAt( j );
                break;
            }
        }
    }

}
コード例 #9
0
ファイル: tagEditor.cpp プロジェクト: ivareske/TagEditor
void TagEditor::showTagInfo(){

    //QModelIndexList indexes = TreeWidget_->selectionModel()->selectedRows();
    QModelIndexList indexes = TreeWidget_->selectionModel()->selectedRows(0);
    //const QModelIndexList qml = TreeWidget_->selectedIndexes();

    if( indexes.size()==0 ){
        return;
    }
    qDebug()<<indexes[0].row()<<TreeWidget_->topLevelItemCount();
    if( indexes.size()==1 && indexes[0].row()>=TreeWidget_->topLevelItemCount() ){
        return;
    }
    if( TreeWidget_->currentItem()==0 ){
        return;
    }

    //qDebug()<<"indexes.size(): "<<indexes.size()<<" currentRow: "<<TreeWidget_->currentRow();
    for(int i=0;i<indexes.size();i++){
        qDebug()<<indexes[i].row();
    }
    if(indexes.size()>1){
        qDebug()<<"multiple rows selected!";
        FileLabel->setText("Pressing the save button when more than one file is selected will store the checked fields for all the selected files! ("+QString::number(indexes.size())+") ");
        return;
    }
    if(indexes.size()==0){
        qDebug()<<"no row selected!";
        FileLabel->setText("");
        clearTextFields();
        return;
    }
    //int row = indexes[0].row();

    //tag
    TagItem *item = (TagItem*)TreeWidget_->currentItem();
    FileLabel->setText( item->fileInfo().absoluteFilePath() );
    if( !item->tagIsRead() ){
        item->readTags();
    }
    TreeWidget_->setColumnData(item);

    if( item->tagOk() ){
        Artist->setText( item->artist() );
        Title->setText( item->title() );
        Album->setText( item->album() );
        Year->setText( QString::number( item->year() ) );
        Track->setText( QString::number( item->track() ) );
        Genre->setText( item->genre() );
        Comment->setText( item->comment() );
    }else{
        clearTextFields();
    }
    //audioproperties
    if( item->audioPropertiesOk() ){
        FileLabel->setText( FileLabel->text() + "\n(Bitrate: "+QString::number(item->bitRate())+" kb/s, samplerate: "+
                           QString::number(item->sampleRate())+" Hz, length: "+QString::number(item->length())+
                           " s, chanels: "+QString::number(item->channels())+")" );
    }else{
        FileLabel->setText( FileLabel->text() + "\n(Could not read tag...)");
    }

}
コード例 #10
0
ファイル: tagEditor.cpp プロジェクト: ivareske/TagEditor
void TagEditor::saveTag(){

    //QModelIndexList indexes = TreeWidget_->selectionModel()->selectedRows();
    QModelIndexList indexes = TreeWidget_->selectionModel()->selectedRows(0);
    qDebug()<<indexes.size();

    if( indexes.size()>1 && showSaveTagWarning ){
        QMessageBox msgBox; QCheckBox dontPrompt("Do not prompt again", &msgBox);
        /*int nrows = (dynamic_cast<QGridLayout*>(msgBox.layout()))->rowCount();
		int ncols = (dynamic_cast<QGridLayout*>(msgBox.layout()))->columnCount();
		dynamic_cast<QGridLayout*>(msgBox.layout())->addWidget(&dontPrompt, nrows, 0, 1, ncols );
		*/
        dontPrompt.blockSignals(true);
        msgBox.addButton(&dontPrompt, QMessageBox::ActionRole);
        msgBox.setText("More than one file is selected");
        msgBox.setInformativeText("Save shown data for all files?");
        msgBox.setStandardButtons(QMessageBox::Save | QMessageBox::Cancel);
        msgBox.setDefaultButton(QMessageBox::Save);
        int ret = msgBox.exec();
        showSaveTagWarning = !dontPrompt.isChecked();
        if(ret==QMessageBox::Cancel){
            statusBar()->showMessage("Aborted", 8000);
            return;
        }
    }
    //aply to all selected files
    QString log;
    int n = indexes.size();
    QProgressDialog *p=0;
    if(n>1){
        p = new QProgressDialog("Saving tags...", "Cancel", 0, indexes.size(), this);
        p->setWindowModality(Qt::WindowModal);
    }
    for(int i=0;i<n;i++){

        if(n>1){
            p->setValue(i);
            if( p->wasCanceled() ){
                break;
            }
        }
	
        int row = indexes[i].row();
        //TagItem *item = (TagItem*)TreeWidget_->topLevelItem( row );
        TagItem *item = TreeWidget_->tagItem(row);
        QString fullfile = item->fileInfo().absoluteFilePath();
        qDebug()<<fullfile;
        //TagLib::FileRef f( fullfile.toStdString().c_str() );
        if( !item->tagOk() ){
            log.append("\nCould not read tag for "+fullfile);
            continue;
        }

        if(ArtistCheckbox->isChecked()){
            //f.tag()->setArtist( Artist->text().toStdString().c_str() );
            //item->setTag( Global::Artist, Artist->text() );
            item->setArtist(Artist->text());
        }
        if(TitleCheckbox->isChecked()){
            //f.tag()->setTitle( Title->text().toStdString().c_str() );
            //item->setTag( Global::Title, Title->text() );
            item->setTitle(Title->text());
        }
        if(AlbumCheckbox->isChecked()){
            //f.tag()->setAlbum( Album->text().toStdString().c_str() );
            //item->setTag( Global::AlbumField, Album->text() );
            item->setAlbum(Album->text());
        }
        if(YearCheckbox->isChecked()){
            bool ok;
            uint year = Year->text().toUInt(&ok);
            qDebug()<<"converted to uint: "<<ok<<year;
            if(!ok){
                //statusBar()->showMessage(fullfile+": Year has to be an positive integer value!", 8000);
                QMessageBox::critical(this, "",
                                      fullfile+":\nYear has to be an positive integer value!",
                                      QMessageBox::Ok, QMessageBox::Ok);
                //Year->setText( item->getTag("year").toString() );
                Year->setText( QString::number(item->year()) );
            }else{
                //f.tag()->setYear( year );
                //item->setTag( Global::Year, year );
                item->setYear(year);
            }
        }
        if(TrackCheckbox->isChecked()){
            bool ok;
            uint track = Track->text().toUInt(&ok);
            if(!ok){
                //statusBar()->showMessage(fullfile+": Track has to be an positive integer value!", 8000);
                QMessageBox::critical(this, "",
                                      fullfile+":\nTrack has to be an positive integer value!",
                                      QMessageBox::Ok, QMessageBox::Ok);
                Track->setText( QString::number(item->track()) );
            }else{
                //f.tag()->setTrack( track );
                //item->setTag( Global::Track, track );
                item->setTrack(track);
            }
        }
        if(GenreCheckbox->isChecked()){
            //f.tag()->setGenre( Genre->text().toStdString().c_str() );
            //item->setTag( Global::Genre, Genre->text() );
            item->setGenre(Genre->text());
        }
        if(CommentCheckbox->isChecked()){
            //f.tag()->setComment( Comment->toPlainText().toStdString().c_str() );
            //item->setTag( Global::Comment, Comment->toPlainText() );
            item->setComment(Comment->toPlainText());
        }

        bool ok = item->saveTag();//f.save();
        if(!ok){
            log.append("\nCould not save tag for "+fullfile);
        }
    }
    if(n>1){
        p->setValue(n);
    }
    if(indexes.size()>1){
        statusBar()->showMessage("Fisnihed saving tags", 8000);
    }else{
        statusBar()->showMessage("Tag saved", 8000);
    }
    if(!log.isEmpty()){
        TextViewer t(log);
        t.exec();        
    }
}
コード例 #11
0
ファイル: SearchDialog.cpp プロジェクト: ivareske/TagEditor
void SearchDialog::save(){


    QString log;
    int aind = searchResults->currentRow();
    if(aind==-1){
        QMessageBox::critical(this, "Save", "Please select a serach result first", QMessageBox::Ok, QMessageBox::Ok);
        return;
    }
    Album album = albums_[searchResults->currentItem()->data(Qt::UserRole).toString()];
    //save tags
    bool trackOk;bool yearOk; QHash<QString,QString> commentsList;
    for(int i=0;i<albumInfo->rowCount();i++){
        qDebug()<<i;
        if( !albumInfo->item(i,TableWidget::FILE_NAME) ){
            continue;
        }
        if( albumInfo->item(i,TableWidget::FILE_NAME)->text().isEmpty() ){
            continue;
        }
        if(albumInfo->item(i,TableWidget::FILE_NAME)->checkState()!=Qt::Checked){
            continue;
        }
        QString fullfile = albumInfo->item(i,TableWidget::FILE_NAME)->data(Qt::UserRole).toString();
        TagItem* tagItem = 0;
        for(int j=0;j<items_.size();j++){
            qDebug()<<items_[j]->fileInfo().filePath().toLower()<<fullfile;
            if(items_[j]->fileInfo().filePath().toLower()==fullfile.toLower()){
                tagItem = items_[j];
                break;
            }
        }
        if(tagItem==0){
            qDebug()<<"BUG!!!!! COULD NOT FIND "+fullfile;
            continue;
        }

        if( !tagItem->tagOk() ){
            log.append("\nCould not read tag for "+fullfile);
            continue;
        }

        qDebug()<<"saving "<<fullfile;
        //title
        if(albumInfo->item(i,TableWidget::TITLE)){
            tagItem->setTitle( albumInfo->item(i,TableWidget::TITLE)->text() );
        }

        //track
        if(albumInfo->item(i,TableWidget::TRACK)){
            int tmp = albumInfo->item(i,TableWidget::TRACK)->text().toInt(&trackOk,10);
            if(trackOk){
                tagItem->setTrack( tmp );
            }
        }
        //add extra info to comments if checked
        QString comments = "";
        if( albumInfo->item(i,TableWidget::COMMENT) && !clearPreviousComentsCheckBox->isChecked() ){
            comments = albumInfo->item(i,TableWidget::COMMENT)->text();
        }
        QString tmp="Format: "+formatLineEdit->text();
        if(formatLabel->isVisible() && formatLabel->isChecked() && !comments.contains(tmp) && !formatLineEdit->text().isEmpty() ){
            if(!comments.isEmpty()){ comments.append("\n"); }
            comments.append(tmp);
        }
        tmp="Country: "+countryLineEdit->text();
        if(countryLabel->isVisible() && countryLabel->isChecked() && !comments.contains(tmp) && !countryLineEdit->text().isEmpty() ){
            if(!comments.isEmpty()){ comments.append("\n"); }
            comments.append(tmp);
        }
        tmp="Label: "+labelLineEdit->text();
        if(labelLabel->isVisible() && labelLabel->isChecked() && !comments.contains(tmp) && !labelLineEdit->text().isEmpty() ){
            if(!comments.isEmpty()){ comments.append("\n"); }
            comments.append(tmp);
        }
        tmp="Roles: "+rolesTextEdit->toPlainText();
        if(rolesLabel->isVisible() && rolesLabel->isChecked() && !comments.contains(tmp) && !rolesTextEdit->toPlainText().isEmpty() ){
            if(!comments.isEmpty()){ comments.append("\n"); }
            comments.append(tmp);
        }
        tmp="Notes: "+notesTextEdit->toPlainText();
        if(notesLabel->isVisible() && notesLabel->isChecked() && !comments.contains(tmp) && !notesTextEdit->toPlainText().isEmpty() ){
            if(!comments.isEmpty()){ comments.append("\n"); }
            comments.append(tmp);
        }
        commentsList.insert(fullfile,comments);
        //comments
        if(albumInfo->item(i,TableWidget::COMMENT)){
            tagItem->setComment( comments );
        }
        //album
        if(albumLabel->isChecked()){
            tagItem->setAlbum( albumLineEdit->text() );
        }
        //artist
        if(artistLabel->isChecked()){
            tagItem->setArtist( artistLineEdit->text() );
        }
        //genre
        if(genreLabel->isVisible() && genreLabel->isChecked()){
            tagItem->setGenre( genreLineEdit->text() );
        }
        //year
        if(yearLabel->isChecked()){
            int tmp = yearLineEdit->text().toInt(&yearOk,10);
            if(yearOk){                
                tagItem->setYear( tmp );
            }            
        }
        bool saveOk = tagItem->saveTag();
        if(!saveOk){
            log.append("\nCould not save tag for "+fullfile);
        }
    }

    //at last, update saved data in table and labels
    setItems();

    //save covers at last, in case tags are used to name covers
    if( saveCoverCheckBox->isChecked() && !saveAllCoversCheckBox->isChecked() ){
        if( currentCoverInd>=0 && currentCoverInd<album.images().size() ){
            QList<QUrl> images = album.images();
            saveCover( images[currentCoverInd] );
        }
    }else if( saveAllCoversCheckBox->isChecked() ){
	//save all covers
        QList<QUrl> images = album.images();
        for(int i=0;i<images.size();i++){
            saveCover( images[i] );
        }
    }
    //show log if any
    if(!log.isEmpty()){
        TextViewer t(log);
        t.exec();
    }
    info->setText("Tags saved");
    //albumInfo->setSortingEnabled(enabled);
}