You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
kipi-plugins/kipi-plugins/batchprocessimages/renameimageswidget.cpp

554 lines
15 KiB

/* ============================================================
*
* This file is a part of kipi-plugins project
* http://www.kipi-plugins.org
*
* Date : 2003-10-01
* Description : a kipi plugin to batch process images
*
* Copyright (C) 2003-2007 by Gilles Caulier <caulier dot gilles at gmail dot com>
* Copyright (C) 2005 by Owen Hirst <n8rider@sbcglobal.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, 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.
*
* ============================================================ */
// C Ansi includes.
extern "C"
{
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
}
// C++ includes.
#include <cstdio>
#include <ctime>
// TQt includes.
#include <tqlistview.h>
#include <tqlineedit.h>
#include <tqcheckbox.h>
#include <tqspinbox.h>
#include <tqfile.h>
#include <tqfileinfo.h>
#include <tqpushbutton.h>
#include <tqlabel.h>
#include <tqcombobox.h>
#include <tqtimer.h>
#include <tqprogressdialog.h>
#include <tqgroupbox.h>
#include <tqpopupmenu.h>
// KDE includes.
#include <tdelocale.h>
#include <tdeconfig.h>
#include <tdeio/previewjob.h>
#include <tdeio/renamedlg.h>
#include <kdebug.h>
#include <tdeversion.h>
// Libkipi includes.
#include <libkipi/interface.h>
#include <libkipi/imageinfo.h>
#include <libkipi/imagedialog.h>
// Local includes.
#include "batchprocessimagesitem.h"
#include "renameimageswidget.h"
#include "renameimageswidget.moc"
namespace KIPIBatchProcessImagesPlugin
{
RenameImagesWidget::RenameImagesWidget(TQWidget *parent,
KIPI::Interface* interface,
const KURL::List& urlList)
: RenameImagesBase(parent),
m_interface(interface),
m_urlList(urlList)
{
m_listView->setSorting(-1);
#if KDE_IS_VERSION(3,4,0)
// next can be done directly into designer but it seems not to compile
// under kde < 3.4.0
m_listView->setShadeSortColumn( FALSE );
#endif
readSettings();
TQPopupMenu* sortMenu = new TQPopupMenu(this);
sortMenu->insertItem(i18n("Sort by Name"), BYNAME);
sortMenu->insertItem(i18n("Sort by Size"), BYSIZE);
sortMenu->insertItem(i18n("Sort by Date"), BYDATE);
m_sortButton->setPopup(sortMenu);
connect(m_listView, TQT_SIGNAL(doubleClicked(TQListViewItem*)),
TQT_SLOT(slotListViewDoubleClicked(TQListViewItem*)));
connect(m_listView, TQT_SIGNAL(selectionChanged(TQListViewItem*)),
TQT_SLOT(slotImageSelected(TQListViewItem*)));
connect(m_prefixEdit, TQT_SIGNAL(textChanged(const TQString&)),
TQT_SLOT(slotOptionsChanged()));
connect(m_seqSpin, TQT_SIGNAL(valueChanged(int)),
TQT_SLOT(slotOptionsChanged()));
connect(m_addFileNameCheck, TQT_SIGNAL(toggled(bool)),
TQT_SLOT(slotOptionsChanged()));
connect(m_addFileDateCheck, TQT_SIGNAL(toggled(bool)),
TQT_SLOT(slotOptionsChanged()));
connect(m_formatDateCheck, TQT_SIGNAL(toggled(bool)),
TQT_SLOT(slotOptionsChanged()));
connect(m_formatDateEdit, TQT_SIGNAL(textChanged(const TQString&)),
TQT_SLOT(slotOptionsChanged()));
connect(m_addButton, TQT_SIGNAL(clicked()),
TQT_SLOT(slotAddImages()));
connect(m_removeButton, TQT_SIGNAL(clicked()),
TQT_SLOT(slotRemoveImage()));
connect(sortMenu, TQT_SIGNAL(activated(int)),
TQT_SLOT(sortList(int)) );
connect(m_reverseList, TQT_SIGNAL(clicked()),
TQT_SLOT(reverseList()) );
connect(m_moveUp, TQT_SIGNAL(clicked()),
TQT_SLOT(moveCurrentItemUp()) );
connect(m_moveDown, TQT_SIGNAL(clicked()),
TQT_SLOT(moveCurrentItemDown()) );
m_timer = new TQTimer(this);
m_progress = new TQProgressDialog(this, 0, true);
connect(m_timer, TQT_SIGNAL(timeout()),
TQT_SLOT(slotNext()));
connect(m_progress, TQT_SIGNAL(canceled()),
TQT_SLOT(slotAbort()));
for (KURL::List::iterator it = m_urlList.begin();
it != m_urlList.end(); ++it)
{
new BatchProcessImagesItem(m_listView,
(*it).path().section('/', 0, -1),
(*it).filename(),
TQString(),
TQString());
}
updateListing();
}
RenameImagesWidget::~RenameImagesWidget()
{
delete m_timer;
delete m_progress;
saveSettings();
}
void RenameImagesWidget::readSettings()
{
TDEConfig config("kipirc");
config.setGroup("RenameImages Settings");
m_prefixEdit->setText(config.readEntry("PrefixString", ""));
m_seqSpin->setValue(config.readNumEntry("FirstRenameValue", 1));
m_addFileNameCheck->setChecked(config.readBoolEntry("AddOriginalFileName", false));
m_addFileDateCheck->setChecked(config.readBoolEntry("AddImageFileDate", false));
m_formatDateCheck->setChecked(config.readBoolEntry("FormatDate", false));
m_formatDateEdit->setText(config.readEntry("FormatDateString", "%Y-%m-%d"));
slotOptionsChanged();
}
void RenameImagesWidget::saveSettings()
{
TDEConfig config("kipirc");
config.setGroup("RenameImages Settings");
config.writeEntry("PrefixString", m_prefixEdit->text());
config.writeEntry("FirstRenameValue", m_seqSpin->value());
config.writeEntry("AddOriginalFileName", m_addFileNameCheck->isChecked());
config.writeEntry("AddImageFileDate", m_addFileDateCheck->isChecked());
config.writeEntry("FormatDate", m_formatDateCheck->isChecked());
config.writeEntry("FormatDateString", m_formatDateEdit->text());
config.sync();
}
void RenameImagesWidget::slotOptionsChanged()
{
m_formatDateCheck->setEnabled(m_addFileDateCheck->isChecked());
m_formatDateEdit->setEnabled(m_formatDateCheck->isEnabled() &&
m_formatDateCheck->isChecked());
updateListing();
}
void RenameImagesWidget::slotListViewDoubleClicked(TQListViewItem*)
{
// TODO: Implement
}
void RenameImagesWidget::slotImageSelected(TQListViewItem* item)
{
if (!item)
{
m_removeButton->setEnabled(false);
return;
}
m_removeButton->setEnabled(true);
m_pixLabel->clear();
BatchProcessImagesItem* it = static_cast<BatchProcessImagesItem*>(item);
TDEIO::PreviewJob* thumbJob = TDEIO::filePreview(KURL(it->pathSrc()),
m_pixLabel->height() );
connect(thumbJob, TQT_SIGNAL(gotPreview(const KFileItem*, const TQPixmap&)),
TQT_SLOT(slotGotPreview(const KFileItem*, const TQPixmap&)));
}
void RenameImagesWidget::sortList(int intSortOrder)
{
SortOrder sortOrder = static_cast<SortOrder>(intSortOrder);
for (TQListViewItem* it = m_listView->firstChild(); it;
it = it->nextSibling())
{
BatchProcessImagesItem* item = static_cast<BatchProcessImagesItem*>(it);
switch (sortOrder)
{
case(BYNAME):
{
item->setKey(item->text(1), false);
break;
}
case(BYSIZE):
{
TQFileInfo fi(item->pathSrc());
item->setKey(TQString::number(fi.size()), false);
break;
}
case(BYDATE):
{
KURL url(item->pathSrc());
KIPI::ImageInfo info = m_interface->info(url);
item->setKey(info.time().toString(TQt::ISODate), false);
break;
}
}
};
// Update list order. We need to set the sorting column temporarily
// otherwise sort() won't do anything
m_listView->setSorting(1);
m_listView->sort();
m_listView->setSorting(-1);
updateListing();
}
void RenameImagesWidget::reverseList()
{
if (m_listView->childCount() < 2) return;
TQListViewItem* lastItem = m_listView->lastItem();
while (m_listView->firstChild() != lastItem) {
m_listView->firstChild()->moveItem(lastItem);
}
updateListing();
}
void RenameImagesWidget::moveCurrentItemUp() {
TQListViewItem* currentItem = m_listView->currentItem();
if (!currentItem) return;
for (TQListViewItem* previousItem = m_listView->firstChild(); previousItem;
previousItem = previousItem->nextSibling())
{
if (previousItem->nextSibling() == currentItem) {
previousItem->moveItem(currentItem);
break;
}
}
updateListing();
}
void RenameImagesWidget::moveCurrentItemDown() {
TQListViewItem* currentItem = m_listView->currentItem();
if (!currentItem) return;
TQListViewItem* nextItem = currentItem->nextSibling();
if (nextItem) {
currentItem->moveItem(nextItem);
}
updateListing();
}
void RenameImagesWidget::updateListing()
{
int pos = 0;
for (TQListViewItem* it = m_listView->firstChild(); it;
it = it->nextSibling())
{
BatchProcessImagesItem* item = static_cast<BatchProcessImagesItem*>(it);
item->changeNameDest(oldToNewName(item, pos));
item->changeResult(TQString());
item->changeError(TQString());
item->changeOutputMess(TQString());
pos++;
}
}
TQString RenameImagesWidget::oldToNewName(BatchProcessImagesItem* item,
int itemPosition)
{
KURL url;
url.setPath(item->pathSrc());
TQFileInfo fi(item->pathSrc());
KIPI::ImageInfo info = m_interface->info(url);
TQString newName = m_prefixEdit->text();
if (m_addFileNameCheck->isChecked())
{
newName += fi.baseName();
newName += "_";
}
if (m_addFileDateCheck->isChecked())
{
TQString format = m_formatDateEdit->text();
format = format.simplifyWhiteSpace();
format.replace("%%","%");
format.replace("%s","");
format.replace("/", "");
time_t time = info.time().toTime_t();
struct tm* time_tm = ::localtime(&time);
char s[100];
::strftime(s, 100, TQFile::encodeName(format), time_tm);
newName += TQString::fromLatin1(s);
newName += "_";
}
int count = m_listView->childCount();
int numDigits = 1;
while (count > 0)
{
numDigits++;
count = count / 10;
}
TQString format;
format.sprintf("0%dd", numDigits);
format = "%" + format;
TQString seq;
seq.sprintf(format.latin1(), itemPosition + m_seqSpin->value());
newName += seq;
newName += TQString::fromLatin1(".") + fi.extension();
return newName;
}
void RenameImagesWidget::slotGotPreview(const KFileItem*, const TQPixmap& pix)
{
m_pixLabel->setPixmap(pix);
}
void RenameImagesWidget::slotStart()
{
m_timer->start(0, true);
m_listView->setSelected(m_listView->firstChild(), true);
m_listView->ensureItemVisible(m_listView->firstChild());
m_progress->setTotalSteps(m_listView->childCount());
m_progress->setProgress(0);
m_progress->show();
m_overwriteAll = false;
m_autoSkip = false;
}
void RenameImagesWidget::slotAbort()
{
m_timer->stop();
m_progress->reset();
m_progress->hide();
}
void RenameImagesWidget::slotNext()
{
TQListViewItem* it = m_listView->selectedItem();
if (!it)
{
slotAbort();
return;
}
BatchProcessImagesItem* item = static_cast<BatchProcessImagesItem*>(it);
KURL src;
src.setPath(item->pathSrc());
KURL dst = src.upURL();
dst.addPath(item->text(2));
bool skip = false;
bool overwrite = false;
if (!m_overwriteAll)
{
struct stat info;
while (::stat(TQFile::encodeName(dst.path()), &info) == 0)
{
if (m_autoSkip)
{
skip = true;
break;
}
TDEIO::RenameDlg dlg(this, i18n("Rename File"), src.path(), dst.path(),
TDEIO::RenameDlg_Mode(TDEIO::M_MULTI |
TDEIO::M_OVERWRITE |
TDEIO::M_SKIP));
int result = dlg.exec();
dst = dlg.newDestURL();
switch (result)
{
case TDEIO::R_CANCEL:
{
slotAbort();
return;
}
case TDEIO::R_SKIP:
{
skip = true;
break;
}
case TDEIO::R_AUTO_SKIP:
{
m_autoSkip = true;
skip = true;
break;
}
case TDEIO::R_OVERWRITE:
{
overwrite = true;
break;
}
case TDEIO::R_OVERWRITE_ALL:
{
m_overwriteAll = true;
overwrite = true;
break;
}
default:
break;
}
if (skip || overwrite)
break;
}
}
if (skip)
{
item->changeResult(i18n("Skipped"));
}
else
{
// Get the src info
KIPI::ImageInfo srcInfo = m_interface->info(src);
if (::rename(TQFile::encodeName(src.path()),
TQFile::encodeName(dst.path())) == 0)
{
srcInfo.setTitle(dst.filename());
item->changeResult(i18n("OK"));
}
else
{
item->changeResult(i18n("Failed"));
}
}
m_progress->setProgress(m_progress->progress() + 1);
if (it->nextSibling())
{
m_listView->setSelected(it->nextSibling(), true);
m_listView->ensureItemVisible(it->nextSibling());
m_timer->start(0, true);
}
}
void RenameImagesWidget::slotAddImages()
{
KURL::List urls = KIPI::ImageDialog::getImageURLs(this, m_interface);
for (KURL::List::iterator it = urls.begin(); it != urls.end(); ++it)
{
if (m_urlList.contains(*it))
continue;
new BatchProcessImagesItem(m_listView,
(*it).path().section('/', 0, -1),
(*it).filename(),
TQString(),
TQString());
m_urlList.append(*it);
}
updateListing();
}
void RenameImagesWidget::slotRemoveImage()
{
if (!m_listView->selectedItem())
return;
BatchProcessImagesItem* item =
static_cast<BatchProcessImagesItem*>(m_listView->selectedItem());
delete item;
m_pixLabel->clear();
updateListing();
}
} // namespace KIPIBatchProcessImagesPlugin