|
|
|
|
|
|
|
/*
|
|
|
|
Copyright (c) 2003,2004,2005 Clarence Dang <dang@kde.org>
|
|
|
|
All rights reserved.
|
|
|
|
|
|
|
|
Redistribution and use in source and binary forms, with or without
|
|
|
|
modification, are permitted provided that the following conditions
|
|
|
|
are met:
|
|
|
|
|
|
|
|
1. Redistributions of source code must retain the above copyright
|
|
|
|
notice, this list of conditions and the following disclaimer.
|
|
|
|
2. Redistributions in binary form must reproduce the above copyright
|
|
|
|
notice, this list of conditions and the following disclaimer in the
|
|
|
|
documentation and/or other materials provided with the distribution.
|
|
|
|
|
|
|
|
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
|
|
|
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
|
|
|
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
|
|
|
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
|
|
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
|
|
|
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
|
|
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
|
|
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
|
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
|
|
|
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#define DEBUG_KP_TOOL_PREVIEW_DIALOG 0
|
|
|
|
|
|
|
|
#include <kptoolpreviewdialog.h>
|
|
|
|
|
|
|
|
#include <tqapplication.h>
|
|
|
|
#include <tqlayout.h>
|
|
|
|
#include <tqgroupbox.h>
|
|
|
|
#include <tqlabel.h>
|
|
|
|
#include <tqpushbutton.h>
|
|
|
|
|
|
|
|
#include <kdebug.h>
|
|
|
|
#include <klocale.h>
|
|
|
|
|
|
|
|
#include <kpcolor.h>
|
|
|
|
#include <kpdocument.h>
|
|
|
|
#include <kpmainwindow.h>
|
|
|
|
#include <kppixmapfx.h>
|
|
|
|
#include <kpresizesignallinglabel.h>
|
|
|
|
#include <kpselection.h>
|
|
|
|
|
|
|
|
|
|
|
|
kpToolPreviewDialog::kpToolPreviewDialog (Features features,
|
|
|
|
bool reserveTopRow,
|
|
|
|
const TQString &caption,
|
|
|
|
const TQString &afterActionText,
|
|
|
|
bool actOnSelection,
|
|
|
|
kpMainWindow *parent,
|
|
|
|
const char *name)
|
|
|
|
: KDialogBase (parent, name, true/*modal*/,
|
|
|
|
caption,
|
|
|
|
KDialogBase::Ok | KDialogBase::Cancel),
|
|
|
|
m_afterActionText (afterActionText),
|
|
|
|
m_actOnSelection (actOnSelection),
|
|
|
|
m_mainWindow (parent),
|
|
|
|
m_dimensionsGroupBox (0),
|
|
|
|
m_afterTransformDimensionsLabel (0),
|
|
|
|
m_previewGroupBox (0),
|
|
|
|
m_previewPixmapLabel (0),
|
|
|
|
m_gridLayout (0)
|
|
|
|
{
|
|
|
|
TQWidget *baseWidget = new TQWidget (this);
|
|
|
|
setMainWidget (baseWidget);
|
|
|
|
|
|
|
|
|
|
|
|
if (document ())
|
|
|
|
{
|
|
|
|
m_oldWidth = document ()->width (actOnSelection);
|
|
|
|
m_oldHeight = document ()->height (actOnSelection);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
m_oldWidth = m_oldHeight = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (features & Dimensions)
|
|
|
|
createDimensionsGroupBox ();
|
|
|
|
|
|
|
|
if (features & Preview)
|
|
|
|
createPreviewGroupBox ();
|
|
|
|
|
|
|
|
|
|
|
|
m_gridLayout = new TQGridLayout (baseWidget, 4, 2,
|
|
|
|
0/*margin*/, spacingHint ());
|
|
|
|
m_gridNumRows = reserveTopRow ? 1 : 0;
|
|
|
|
if (m_dimensionsGroupBox || m_previewGroupBox)
|
|
|
|
{
|
|
|
|
if (m_dimensionsGroupBox && m_previewGroupBox)
|
|
|
|
{
|
|
|
|
m_gridLayout->addWidget (m_dimensionsGroupBox, m_gridNumRows, 0);
|
|
|
|
m_gridLayout->addWidget (m_previewGroupBox, m_gridNumRows, 1);
|
|
|
|
|
|
|
|
m_gridLayout->setColStretch (1, 1);
|
|
|
|
}
|
|
|
|
else if (m_dimensionsGroupBox)
|
|
|
|
{
|
|
|
|
m_gridLayout->addMultiCellWidget (m_dimensionsGroupBox,
|
|
|
|
m_gridNumRows, m_gridNumRows, 0, 1);
|
|
|
|
}
|
|
|
|
else if (m_previewGroupBox)
|
|
|
|
{
|
|
|
|
m_gridLayout->addMultiCellWidget (m_previewGroupBox,
|
|
|
|
m_gridNumRows, m_gridNumRows, 0, 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
m_gridLayout->setRowStretch (m_gridNumRows, 1);
|
|
|
|
m_gridNumRows++;;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
kpToolPreviewDialog::~kpToolPreviewDialog ()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// private
|
|
|
|
void kpToolPreviewDialog::createDimensionsGroupBox ()
|
|
|
|
{
|
|
|
|
m_dimensionsGroupBox = new TQGroupBox (i18n ("Dimensions"), mainWidget ());
|
|
|
|
|
|
|
|
TQLabel *originalLabel = new TQLabel (i18n ("Original:"), m_dimensionsGroupBox);
|
|
|
|
TQString originalDimensions;
|
|
|
|
if (document ())
|
|
|
|
{
|
|
|
|
originalDimensions = i18n ("%1 x %2")
|
|
|
|
.arg (m_oldWidth)
|
|
|
|
.arg (m_oldHeight);
|
|
|
|
|
|
|
|
// Stop the Dimensions Group Box from resizing so often
|
|
|
|
const TQString minimumLengthString ("100000 x 100000");
|
|
|
|
const int padLength = minimumLengthString.length ();
|
|
|
|
for (int i = originalDimensions.length (); i < padLength; i++)
|
|
|
|
originalDimensions += " ";
|
|
|
|
}
|
|
|
|
TQLabel *originalDimensionsLabel = new TQLabel (originalDimensions, m_dimensionsGroupBox);
|
|
|
|
|
|
|
|
TQLabel *afterTransformLabel = new TQLabel (m_afterActionText, m_dimensionsGroupBox);
|
|
|
|
m_afterTransformDimensionsLabel = new TQLabel (m_dimensionsGroupBox);
|
|
|
|
|
|
|
|
|
|
|
|
TQGridLayout *dimensionsLayout = new TQGridLayout (m_dimensionsGroupBox,
|
|
|
|
2, 2,
|
|
|
|
marginHint () * 2, spacingHint ());
|
|
|
|
|
|
|
|
dimensionsLayout->addWidget (originalLabel, 0, 0, Qt::AlignBottom);
|
|
|
|
dimensionsLayout->addWidget (originalDimensionsLabel, 0, 1, Qt::AlignBottom);
|
|
|
|
dimensionsLayout->addWidget (afterTransformLabel, 1, 0, Qt::AlignTop);
|
|
|
|
dimensionsLayout->addWidget (m_afterTransformDimensionsLabel, 1, 1, Qt::AlignTop);
|
|
|
|
}
|
|
|
|
|
|
|
|
// private
|
|
|
|
void kpToolPreviewDialog::createPreviewGroupBox ()
|
|
|
|
{
|
|
|
|
m_previewGroupBox = new TQGroupBox (i18n ("Preview"), mainWidget ());
|
|
|
|
|
|
|
|
m_previewPixmapLabel = new kpResizeSignallingLabel (m_previewGroupBox);
|
|
|
|
m_previewPixmapLabel->setMinimumSize (150, 110);
|
|
|
|
connect (m_previewPixmapLabel, TQT_SIGNAL (resized ()),
|
|
|
|
this, TQT_SLOT (updatePreview ()));
|
|
|
|
|
|
|
|
TQPushButton *updatePushButton = new TQPushButton (i18n ("&Update"),
|
|
|
|
m_previewGroupBox);
|
|
|
|
connect (updatePushButton, TQT_SIGNAL (clicked ()),
|
|
|
|
this, TQT_SLOT (slotUpdateWithWaitCursor ()));
|
|
|
|
|
|
|
|
|
|
|
|
TQVBoxLayout *previewLayout = new TQVBoxLayout (m_previewGroupBox,
|
|
|
|
marginHint () * 2,
|
|
|
|
QMAX (1, spacingHint () / 2));
|
|
|
|
|
|
|
|
previewLayout->addWidget (m_previewPixmapLabel, 1/*stretch*/);
|
|
|
|
previewLayout->addWidget (updatePushButton, 0/*stretch*/, Qt::AlignHCenter);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// protected
|
|
|
|
kpDocument *kpToolPreviewDialog::document () const
|
|
|
|
{
|
|
|
|
return m_mainWindow ? m_mainWindow->document () : 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// protected
|
|
|
|
void kpToolPreviewDialog::addCustomWidgetToFront (TQWidget *w)
|
|
|
|
{
|
|
|
|
m_gridLayout->addMultiCellWidget (w, 0, 0, 0, 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
// protected
|
|
|
|
void kpToolPreviewDialog::addCustomWidget (TQWidget *w)
|
|
|
|
{
|
|
|
|
m_gridLayout->addMultiCellWidget (w, m_gridNumRows, m_gridNumRows, 0, 1);
|
|
|
|
m_gridNumRows++;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// private
|
|
|
|
void kpToolPreviewDialog::updateDimensions ()
|
|
|
|
{
|
|
|
|
if (!m_dimensionsGroupBox)
|
|
|
|
return;
|
|
|
|
|
|
|
|
kpDocument *doc = document ();
|
|
|
|
if (!doc)
|
|
|
|
return;
|
|
|
|
|
|
|
|
TQSize newDim = newDimensions ();
|
|
|
|
#if DEBUG_KP_TOOL_PREVIEW_DIALOG
|
|
|
|
kdDebug () << "kpToolPreviewDialog::updateDimensions(): newDim=" << newDim << endl;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
TQString newDimString = i18n ("%1 x %2")
|
|
|
|
.arg (newDim.width ())
|
|
|
|
.arg (newDim.height ());
|
|
|
|
m_afterTransformDimensionsLabel->setText (newDimString);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// public static
|
|
|
|
double kpToolPreviewDialog::aspectScale (int newWidth, int newHeight,
|
|
|
|
int oldWidth, int oldHeight)
|
|
|
|
{
|
|
|
|
double widthScale = double (newWidth) / double (oldWidth);
|
|
|
|
double heightScale = double (newHeight) / double (oldHeight);
|
|
|
|
|
|
|
|
// Keeps aspect ratio
|
|
|
|
return QMIN (widthScale, heightScale);
|
|
|
|
}
|
|
|
|
|
|
|
|
// public static
|
|
|
|
int kpToolPreviewDialog::scaleDimension (int dimension, double scale, int min, int max)
|
|
|
|
{
|
|
|
|
return QMAX (min,
|
|
|
|
QMIN (max,
|
|
|
|
qRound (dimension * scale)));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// private
|
|
|
|
void kpToolPreviewDialog::updateShrukenDocumentPixmap ()
|
|
|
|
{
|
|
|
|
#if DEBUG_KP_TOOL_PREVIEW_DIALOG
|
|
|
|
kdDebug () << "kpToolPreviewDialog::updateShrukenDocumentPixmap()"
|
|
|
|
<< " shrunkenDocPixmap.size="
|
|
|
|
<< m_shrunkenDocumentPixmap.size ()
|
|
|
|
<< " previewPixmapLabelSizeWhenUpdatedPixmap="
|
|
|
|
<< m_previewPixmapLabelSizeWhenUpdatedPixmap
|
|
|
|
<< " previewPixmapLabel.size="
|
|
|
|
<< m_previewPixmapLabel->size ()
|
|
|
|
<< endl;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if (!m_previewGroupBox)
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
|
|
kpDocument *doc = document ();
|
|
|
|
if (!doc || !doc->pixmap ())
|
|
|
|
{
|
|
|
|
kdError () << "kpToolPreviewDialog::updateShrunkenDocumentPixmap() doc="
|
|
|
|
<< doc << endl;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (m_shrunkenDocumentPixmap.isNull () ||
|
|
|
|
m_previewPixmapLabel->size () != m_previewPixmapLabelSizeWhenUpdatedPixmap)
|
|
|
|
{
|
|
|
|
#if DEBUG_KP_TOOL_PREVIEW_DIALOG
|
|
|
|
kdDebug () << "\tupdating shrunkenDocPixmap" << endl;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
// TODO: Why the need to keep aspect ratio here?
|
|
|
|
// Isn't scaling the skewed result maintaining aspect enough?
|
|
|
|
double keepsAspectScale = aspectScale (m_previewPixmapLabel->width (),
|
|
|
|
m_previewPixmapLabel->height (),
|
|
|
|
m_oldWidth,
|
|
|
|
m_oldHeight);
|
|
|
|
|
|
|
|
TQPixmap pixmap;
|
|
|
|
|
|
|
|
if (m_actOnSelection)
|
|
|
|
{
|
|
|
|
kpSelection sel = *doc->selection ();
|
|
|
|
if (!sel.pixmap ())
|
|
|
|
sel.setPixmap (doc->getSelectedPixmap ());
|
|
|
|
|
|
|
|
pixmap = sel.transparentPixmap ();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
pixmap = *doc->pixmap ();
|
|
|
|
}
|
|
|
|
|
|
|
|
m_shrunkenDocumentPixmap = kpPixmapFX::scale (
|
|
|
|
pixmap,
|
|
|
|
scaleDimension (m_oldWidth,
|
|
|
|
keepsAspectScale,
|
|
|
|
1, m_previewPixmapLabel->width ()),
|
|
|
|
scaleDimension (m_oldHeight,
|
|
|
|
keepsAspectScale,
|
|
|
|
1, m_previewPixmapLabel->height ()));
|
|
|
|
#if 0
|
|
|
|
m_shrunkenDocumentPixmap = kpPixmapFX::scale (
|
|
|
|
m_actOnSelection ? doc->getSelectedPixmap () : *doc->pixmap (),
|
|
|
|
m_previewPixmapLabel->width (),
|
|
|
|
m_previewPixmapLabel->height ());
|
|
|
|
#endif
|
|
|
|
|
|
|
|
m_previewPixmapLabelSizeWhenUpdatedPixmap = m_previewPixmapLabel->size ();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// private
|
|
|
|
void kpToolPreviewDialog::updatePreview ()
|
|
|
|
{
|
|
|
|
#if DEBUG_KP_TOOL_PREVIEW_DIALOG
|
|
|
|
kdDebug () << "kpToolPreviewDialog::updatePreview()" << endl;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if (!m_previewGroupBox)
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
|
|
kpDocument *doc = document ();
|
|
|
|
if (!doc)
|
|
|
|
return;
|
|
|
|
|
|
|
|
updateShrukenDocumentPixmap ();
|
|
|
|
|
|
|
|
if (!m_shrunkenDocumentPixmap.isNull ())
|
|
|
|
{
|
|
|
|
TQSize newDim = newDimensions ();
|
|
|
|
double keepsAspectScale = aspectScale (m_previewPixmapLabel->width (),
|
|
|
|
m_previewPixmapLabel->height (),
|
|
|
|
newDim.width (),
|
|
|
|
newDim.height ());
|
|
|
|
|
|
|
|
int targetWidth = scaleDimension (newDim.width (),
|
|
|
|
keepsAspectScale,
|
|
|
|
1, // min
|
|
|
|
m_previewPixmapLabel->width ()); // max
|
|
|
|
int targetHeight = scaleDimension (newDim.height (),
|
|
|
|
keepsAspectScale,
|
|
|
|
1, // min
|
|
|
|
m_previewPixmapLabel->height ()); // max
|
|
|
|
|
|
|
|
// TODO: Some effects work directly on TQImage; so could cache the
|
|
|
|
// TQImage so that transformPixmap() is faster
|
|
|
|
TQPixmap transformedShrunkenDocumentPixmap =
|
|
|
|
transformPixmap (m_shrunkenDocumentPixmap, targetWidth, targetHeight);
|
|
|
|
|
|
|
|
TQPixmap previewPixmap (m_previewPixmapLabel->width (),
|
|
|
|
m_previewPixmapLabel->height ());
|
|
|
|
kpPixmapFX::fill (&previewPixmap, kpColor::transparent);
|
|
|
|
kpPixmapFX::setPixmapAt (&previewPixmap,
|
|
|
|
(previewPixmap.width () - transformedShrunkenDocumentPixmap.width ()) / 2,
|
|
|
|
(previewPixmap.height () - transformedShrunkenDocumentPixmap.height ()) / 2,
|
|
|
|
transformedShrunkenDocumentPixmap);
|
|
|
|
|
|
|
|
#if DEBUG_KP_TOOL_PREVIEW_DIALOG
|
|
|
|
kdDebug () << "kpToolPreviewDialog::updatePreview ():"
|
|
|
|
<< " shrunkenDocumentPixmap: w="
|
|
|
|
<< m_shrunkenDocumentPixmap.width ()
|
|
|
|
<< " h="
|
|
|
|
<< m_shrunkenDocumentPixmap.height ()
|
|
|
|
<< " previewPixmapLabel: w="
|
|
|
|
<< m_previewPixmapLabel->width ()
|
|
|
|
<< " h="
|
|
|
|
<< m_previewPixmapLabel->height ()
|
|
|
|
<< " transformedShrunkenDocumentPixmap: w="
|
|
|
|
<< transformedShrunkenDocumentPixmap.width ()
|
|
|
|
<< " h="
|
|
|
|
<< transformedShrunkenDocumentPixmap.height ()
|
|
|
|
<< " previewPixmap: w="
|
|
|
|
<< previewPixmap.width ()
|
|
|
|
<< " h="
|
|
|
|
<< previewPixmap.height ()
|
|
|
|
<< endl;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
m_previewPixmapLabel->setPixmap (previewPixmap);
|
|
|
|
|
|
|
|
// immediate update esp. for expensive previews
|
|
|
|
m_previewPixmapLabel->repaint (false/*no erase*/);
|
|
|
|
|
|
|
|
#if DEBUG_KP_TOOL_PREVIEW_DIALOG
|
|
|
|
kdDebug () << "\tafter TQLabel::setPixmap() previewPixmapLabel: w="
|
|
|
|
<< m_previewPixmapLabel->width ()
|
|
|
|
<< " h="
|
|
|
|
<< m_previewPixmapLabel->height ()
|
|
|
|
<< endl;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// protected slot virtual
|
|
|
|
void kpToolPreviewDialog::slotUpdate ()
|
|
|
|
{
|
|
|
|
#if DEBUG_KP_TOOL_PREVIEW_DIALOG
|
|
|
|
kdDebug () << "kpToolPreviewDialog::slotUpdate()" << endl;
|
|
|
|
#endif
|
|
|
|
updateDimensions ();
|
|
|
|
updatePreview ();
|
|
|
|
}
|
|
|
|
|
|
|
|
// protected slot virtual
|
|
|
|
void kpToolPreviewDialog::slotUpdateWithWaitCursor ()
|
|
|
|
{
|
|
|
|
#if DEBUG_KP_TOOL_PREVIEW_DIALOG
|
|
|
|
kdDebug () << "kpToolPreviewDialog::slotUpdateWithWaitCursor()"
|
|
|
|
<< endl;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
TQApplication::setOverrideCursor (Qt::waitCursor);
|
|
|
|
|
|
|
|
slotUpdate ();
|
|
|
|
|
|
|
|
TQApplication::restoreOverrideCursor ();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#include <kptoolpreviewdialog.moc>
|