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.
504 lines
15 KiB
504 lines
15 KiB
/* ============================================================
|
|
*
|
|
* This file is a part of kipi-plugins project
|
|
* http://www.kipi-plugins.org
|
|
*
|
|
* Date : 2003-09-26
|
|
* Description : loss less images transformations plugin.
|
|
*
|
|
* Copyright (C) 2003-2005 by Renchi Raju <renchi@pooh.tam.uiuc.edu>
|
|
* Copyright (C) 2004-2007 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de>
|
|
* Copyright (C) 2006-2007 by Gilles Caulier <caulier dot gilles at gmail dot com>
|
|
*
|
|
* 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++ includes.
|
|
|
|
#include <iostream>
|
|
|
|
// TQt includes.
|
|
|
|
#include <tqdir.h>
|
|
|
|
// KDE includes.
|
|
|
|
#include <tdelocale.h>
|
|
#include <tdeaction.h>
|
|
#include <kgenericfactory.h>
|
|
#include <klibloader.h>
|
|
#include <tdeconfig.h>
|
|
#include <kdebug.h>
|
|
#include <kurl.h>
|
|
#include <tdemessagebox.h>
|
|
#include <tdeapplication.h>
|
|
|
|
// LibKipi includes.
|
|
|
|
#include <libkipi/batchprogressdialog.h>
|
|
#include <libkipi/interface.h>
|
|
|
|
// Local includes.
|
|
|
|
#include "actions.h"
|
|
#include "actionthread.h"
|
|
#include "plugin_jpeglossless.h"
|
|
#include "plugin_jpeglossless.moc"
|
|
|
|
typedef KGenericFactory<Plugin_JPEGLossless> Factory;
|
|
|
|
K_EXPORT_COMPONENT_FACTORY( kipiplugin_jpeglossless,
|
|
Factory("kipiplugin_jpeglossless"))
|
|
|
|
Plugin_JPEGLossless::Plugin_JPEGLossless(TQObject *parent, const char*, const TQStringList &)
|
|
: KIPI::Plugin( Factory::instance(), parent, "JPEGLossless")
|
|
{
|
|
m_total = 0;
|
|
m_current = 0;
|
|
m_action_Convert2GrayScale = 0;
|
|
m_action_AutoExif = 0;
|
|
m_action_RotateImage = 0;
|
|
m_action_FlipImage = 0;
|
|
m_progressDlg = 0;
|
|
m_thread = 0;
|
|
m_failed = false;
|
|
|
|
kdDebug( 51001 ) << "Plugin_JPEGLossless plugin loaded" << endl;
|
|
}
|
|
|
|
void Plugin_JPEGLossless::setup( TQWidget* widget )
|
|
{
|
|
KIPI::Plugin::setup( widget );
|
|
|
|
m_action_AutoExif = new TDEAction(i18n("Auto Rotate/Flip Using Exif Information"),
|
|
0, 0,
|
|
this,
|
|
TQT_SLOT(slotRotate()),
|
|
actionCollection(),
|
|
"rotate_exif");
|
|
|
|
m_action_RotateImage = new TDEActionMenu(i18n("Rotate"),
|
|
"object-rotate-right",
|
|
actionCollection(),
|
|
"jpeglossless_rotate");
|
|
|
|
m_action_RotateImage->insert( new TDEAction(i18n("Left"),
|
|
"object-rotate-left",
|
|
SHIFT+CTRL+Key_Left,
|
|
this,
|
|
TQT_SLOT(slotRotate()),
|
|
actionCollection(),
|
|
"object-rotate-left") );
|
|
m_action_RotateImage->insert( new TDEAction(i18n("Right"),
|
|
"object-rotate-right",
|
|
SHIFT+CTRL+Key_Right,
|
|
this,
|
|
TQT_SLOT(slotRotate()),
|
|
actionCollection(),
|
|
"object-rotate-right") );
|
|
|
|
m_action_FlipImage = new TDEActionMenu(i18n("Flip"),
|
|
"flip",
|
|
actionCollection(),
|
|
"jpeglossless_flip");
|
|
|
|
m_action_FlipImage->insert( new TDEAction(i18n("Horizontally"),
|
|
0,
|
|
CTRL+Key_Asterisk,
|
|
this,
|
|
TQT_SLOT(slotFlip()),
|
|
actionCollection(),
|
|
"flip_horizontal") );
|
|
|
|
m_action_FlipImage->insert( new TDEAction(i18n("Vertically"),
|
|
0,
|
|
CTRL+Key_Slash,
|
|
this,
|
|
TQT_SLOT(slotFlip()),
|
|
actionCollection(),
|
|
"flip_vertical") );
|
|
|
|
m_action_Convert2GrayScale = new TDEAction(i18n("Convert to Black && White"),
|
|
"grayscaleconvert",
|
|
0,
|
|
this,
|
|
TQT_SLOT(slotConvert2GrayScale()),
|
|
actionCollection(),
|
|
"jpeglossless_convert2grayscale");
|
|
|
|
addAction( m_action_AutoExif );
|
|
addAction( m_action_RotateImage );
|
|
addAction( m_action_FlipImage );
|
|
addAction( m_action_Convert2GrayScale );
|
|
|
|
KIPI::Interface* interface = dynamic_cast<KIPI::Interface*>( parent() );
|
|
|
|
if ( !interface )
|
|
{
|
|
kdError( 51000 ) << "Kipi interface is null!" << endl;
|
|
return;
|
|
}
|
|
|
|
m_action_AutoExif->setEnabled( false );
|
|
m_action_RotateImage->setEnabled( false );
|
|
m_action_FlipImage->setEnabled( false );
|
|
m_action_Convert2GrayScale->setEnabled( false );
|
|
|
|
m_thread = new KIPIJPEGLossLessPlugin::ActionThread(interface, this);
|
|
|
|
connect( interface, TQT_SIGNAL( selectionChanged( bool ) ),
|
|
m_action_AutoExif, TQT_SLOT( setEnabled( bool ) ) );
|
|
|
|
connect( interface, TQT_SIGNAL( selectionChanged( bool ) ),
|
|
m_action_RotateImage, TQT_SLOT( setEnabled( bool ) ) );
|
|
|
|
connect( interface, TQT_SIGNAL( selectionChanged( bool ) ),
|
|
m_action_FlipImage, TQT_SLOT( setEnabled( bool ) ) );
|
|
|
|
connect( interface, TQT_SIGNAL( selectionChanged( bool ) ),
|
|
m_action_Convert2GrayScale, TQT_SLOT( setEnabled( bool ) ) );
|
|
}
|
|
|
|
Plugin_JPEGLossless::~Plugin_JPEGLossless()
|
|
{
|
|
delete m_thread;
|
|
delete m_progressDlg;
|
|
}
|
|
|
|
void Plugin_JPEGLossless::slotFlip()
|
|
{
|
|
KURL::List items = images();
|
|
if (items.count() <= 0) return;
|
|
|
|
TQString from(TQT_TQOBJECT(const_cast<TQT_BASE_OBJECT_NAME*>(sender()))->name());
|
|
TQString title;
|
|
bool proceed = false;
|
|
|
|
if (from == "flip_horizontal")
|
|
{
|
|
m_thread->flip(items, KIPIJPEGLossLessPlugin::FlipHorizontal);
|
|
title = i18n("horizontaly");
|
|
proceed = true;
|
|
}
|
|
else if (from == "flip_vertical")
|
|
{
|
|
m_thread->flip(items, KIPIJPEGLossLessPlugin::FlipVertical);
|
|
title = i18n("vertically");
|
|
proceed = true;
|
|
}
|
|
else
|
|
{
|
|
kdWarning( 51000 ) << "The impossible happened... unknown flip specified" << endl;
|
|
return;
|
|
}
|
|
|
|
if (!proceed) return;
|
|
m_total = items.count();
|
|
m_current = 0;
|
|
m_failed = false;
|
|
|
|
if (m_progressDlg)
|
|
{
|
|
delete m_progressDlg;
|
|
m_progressDlg = 0;
|
|
}
|
|
|
|
m_progressDlg = new KIPI::BatchProgressDialog(TQT_TQWIDGET(kapp->activeWindow()),
|
|
i18n("Flip images %1").arg(title));
|
|
|
|
connect(m_progressDlg, TQT_SIGNAL(cancelClicked()),
|
|
this, TQT_SLOT(slotCancel()));
|
|
|
|
m_progressDlg->show();
|
|
|
|
if (!m_thread->running())
|
|
m_thread->start();
|
|
}
|
|
|
|
void Plugin_JPEGLossless::slotRotate()
|
|
{
|
|
KURL::List items = images();
|
|
if (items.count() <= 0) return;
|
|
|
|
TQString from(TQT_TQOBJECT(const_cast<TQT_BASE_OBJECT_NAME*>(sender()))->name());
|
|
TQString title;
|
|
bool proceed = false;
|
|
|
|
if (from == "object-rotate-right")
|
|
{
|
|
m_thread->rotate(items, KIPIJPEGLossLessPlugin::Rot90);
|
|
title = i18n("right (clockwise)");
|
|
proceed = true;
|
|
}
|
|
else if (from == "object-rotate-left")
|
|
{
|
|
m_thread->rotate(items, KIPIJPEGLossLessPlugin::Rot270);
|
|
title = i18n("left (counterclockwise)");
|
|
proceed = true;
|
|
}
|
|
else if (from == "rotate_exif")
|
|
{
|
|
m_thread->rotate(items, KIPIJPEGLossLessPlugin::Rot0);
|
|
title = i18n("using Exif orientation tag");
|
|
proceed = true;
|
|
}
|
|
else
|
|
{
|
|
kdWarning( 51000 ) << "The impossible happened... unknown rotation angle specified" << endl;
|
|
return;
|
|
}
|
|
|
|
if (!proceed) return;
|
|
m_total = items.count();
|
|
m_current = 0;
|
|
m_failed = false;
|
|
|
|
if (m_progressDlg)
|
|
{
|
|
delete m_progressDlg;
|
|
m_progressDlg = 0;
|
|
}
|
|
|
|
m_progressDlg = new KIPI::BatchProgressDialog(TQT_TQWIDGET(kapp->activeWindow()),
|
|
i18n("Rotate images %1").arg(title));
|
|
|
|
connect(m_progressDlg, TQT_SIGNAL(cancelClicked()),
|
|
this, TQT_SLOT(slotCancel()));
|
|
|
|
m_progressDlg->show();
|
|
|
|
if (!m_thread->running())
|
|
m_thread->start();
|
|
}
|
|
|
|
void Plugin_JPEGLossless::slotConvert2GrayScale()
|
|
{
|
|
KURL::List items = images();
|
|
if (items.count() <= 0 ||
|
|
KMessageBox::No==KMessageBox::warningYesNo(TQT_TQWIDGET(kapp->activeWindow()),
|
|
i18n("<p>Are you sure you wish to convert the selected image(s) to "
|
|
"black and white? This operation <b>cannot</b> be undone.</p>")))
|
|
return;
|
|
|
|
TQString from(TQT_TQOBJECT(const_cast<TQT_BASE_OBJECT_NAME*>(sender()))->name());
|
|
|
|
m_total = items.count();
|
|
m_current = 0;
|
|
m_failed = false;
|
|
|
|
if (m_progressDlg)
|
|
{
|
|
delete m_progressDlg;
|
|
m_progressDlg = 0;
|
|
}
|
|
|
|
m_progressDlg = new KIPI::BatchProgressDialog(TQT_TQWIDGET(kapp->activeWindow()),
|
|
i18n("Convert images to black & white"));
|
|
|
|
connect(m_progressDlg, TQT_SIGNAL(cancelClicked()),
|
|
this, TQT_SLOT(slotCancel()));
|
|
|
|
m_progressDlg->show();
|
|
|
|
m_thread->convert2grayscale(items);
|
|
if (!m_thread->running())
|
|
m_thread->start();
|
|
}
|
|
|
|
void Plugin_JPEGLossless::slotCancel()
|
|
{
|
|
m_thread->cancel();
|
|
|
|
KIPI::Interface* interface = dynamic_cast<KIPI::Interface*>( parent() );
|
|
|
|
if ( !interface )
|
|
{
|
|
kdError( 51000 ) << "Kipi interface is null!" << endl;
|
|
return;
|
|
}
|
|
|
|
interface->refreshImages( m_images );
|
|
}
|
|
|
|
void Plugin_JPEGLossless::customEvent(TQCustomEvent *event)
|
|
{
|
|
if (!event) return;
|
|
|
|
KIPIJPEGLossLessPlugin::EventData *d = (KIPIJPEGLossLessPlugin::EventData*) event->data();
|
|
if (!d) return;
|
|
|
|
TQString text;
|
|
|
|
if (d->starting)
|
|
{
|
|
switch (d->action)
|
|
{
|
|
case(KIPIJPEGLossLessPlugin::Rotate):
|
|
{
|
|
text = i18n("Rotating Image \"%1\"").arg(d->fileName.section('/', -1));
|
|
break;
|
|
}
|
|
case(KIPIJPEGLossLessPlugin::Flip):
|
|
{
|
|
text = i18n("Flipping Image \"%1\"").arg(d->fileName.section('/', -1));
|
|
break;
|
|
}
|
|
case(KIPIJPEGLossLessPlugin::GrayScale):
|
|
{
|
|
text = i18n("Converting to Black & White \"%1\"").arg(d->fileName.section('/', -1));
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
kdWarning( 51000 ) << "KIPIJPEGLossLessPlugin: Unknown event" << endl;
|
|
}
|
|
}
|
|
|
|
m_progressDlg->addedAction(text, KIPI::StartingMessage);
|
|
}
|
|
else
|
|
{
|
|
if (!d->success)
|
|
{
|
|
m_failed = true;
|
|
|
|
switch (d->action)
|
|
{
|
|
case(KIPIJPEGLossLessPlugin::Rotate):
|
|
{
|
|
text = i18n("Failed to Rotate image");
|
|
break;
|
|
}
|
|
case(KIPIJPEGLossLessPlugin::Flip):
|
|
{
|
|
text = i18n("Failed to Flip image");
|
|
break;
|
|
}
|
|
case(KIPIJPEGLossLessPlugin::GrayScale):
|
|
{
|
|
text = i18n("Failed to convert image to Black & White");
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
kdWarning( 51000 ) << "KIPIJPEGLossLessPlugin: Unknown event" << endl;
|
|
}
|
|
}
|
|
|
|
m_progressDlg->addedAction(text, KIPI::WarningMessage);
|
|
|
|
if (!d->errString.isEmpty())
|
|
m_progressDlg->addedAction(d->errString, KIPI::WarningMessage);
|
|
}
|
|
else
|
|
{
|
|
switch (d->action)
|
|
{
|
|
case(KIPIJPEGLossLessPlugin::Rotate):
|
|
{
|
|
text = i18n("Rotate image complete");
|
|
break;
|
|
}
|
|
case(KIPIJPEGLossLessPlugin::Flip):
|
|
{
|
|
text = i18n("Flip image complete");
|
|
break;
|
|
}
|
|
case(KIPIJPEGLossLessPlugin::GrayScale):
|
|
{
|
|
text = i18n("Convert to Black & White complete");
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
kdWarning( 51000 ) << "KIPIJPEGLossLessPlugin: Unknown event" << endl;
|
|
}
|
|
}
|
|
|
|
m_progressDlg->addedAction(text, KIPI::SuccessMessage);
|
|
}
|
|
|
|
m_current++;
|
|
m_progressDlg->setProgress(m_current, m_total);
|
|
}
|
|
|
|
delete d;
|
|
|
|
if (m_current >= m_total)
|
|
{
|
|
m_current = 0;
|
|
|
|
if (m_failed)
|
|
{
|
|
#if TDE_VERSION >= 0x30200
|
|
m_progressDlg->setButtonCancel( KStdGuiItem::close() );
|
|
#else
|
|
m_progressDlg->setButtonCancelText( i18n("&Close") );
|
|
#endif
|
|
|
|
disconnect(m_progressDlg, TQT_SIGNAL(cancelClicked()),
|
|
this, TQT_SLOT(slotCancel()));
|
|
}
|
|
else
|
|
{
|
|
slotCancel();
|
|
m_progressDlg->close();
|
|
m_progressDlg = 0;
|
|
}
|
|
|
|
KIPI::Interface* interface = dynamic_cast<KIPI::Interface*>( parent() );
|
|
|
|
if ( !interface )
|
|
{
|
|
kdError( 51000 ) << "Kipi interface is null!" << endl;
|
|
return;
|
|
}
|
|
|
|
interface->refreshImages( m_images );
|
|
}
|
|
}
|
|
|
|
KIPI::Category Plugin_JPEGLossless::category( TDEAction* action ) const
|
|
{
|
|
if (action == m_action_AutoExif)
|
|
return KIPI::IMAGESPLUGIN;
|
|
else if ( action == m_action_RotateImage )
|
|
return KIPI::IMAGESPLUGIN;
|
|
else if ( action == m_action_FlipImage )
|
|
return KIPI::IMAGESPLUGIN;
|
|
else if ( action == m_action_Convert2GrayScale )
|
|
return KIPI::IMAGESPLUGIN;
|
|
|
|
kdWarning( 51000 ) << "Unrecognized action for plugin category identification" << endl;
|
|
return KIPI::IMAGESPLUGIN; // no warning from compiler, please
|
|
}
|
|
|
|
KURL::List Plugin_JPEGLossless::images()
|
|
{
|
|
KIPI::Interface* interface = dynamic_cast<KIPI::Interface*>( parent() );
|
|
|
|
if ( !interface )
|
|
{
|
|
kdError( 51000 ) << "Kipi interface is null!" << endl;
|
|
return KURL::List();
|
|
}
|
|
|
|
KIPI::ImageCollection images = interface->currentSelection();
|
|
if ( !images.isValid() )
|
|
return KURL::List();
|
|
|
|
// We don't want the set of images to change before we are done
|
|
// and tells the host app to refresh the images.
|
|
m_images = images.images();
|
|
return images.images();
|
|
}
|