summaryrefslogtreecommitdiff
Side-by-side diff
Diffstat (more/less context) (show whitespace changes)
-rw-r--r--libopie2/opieui/odialog.cpp10
-rw-r--r--libopie2/opieui/odialog.h10
-rw-r--r--libopie2/opieui/oimageeffect.cpp41
-rw-r--r--libopie2/opieui/olistview.cpp20
-rw-r--r--libopie2/opieui/opieui.pro10
-rw-r--r--libopie2/opieui/oseparator.cpp12
-rw-r--r--libopie2/opieui/oversatileview.cpp25
7 files changed, 66 insertions, 62 deletions
diff --git a/libopie2/opieui/odialog.cpp b/libopie2/opieui/odialog.cpp
index 00a7a7e..4d269d4 100644
--- a/libopie2/opieui/odialog.cpp
+++ b/libopie2/opieui/odialog.cpp
@@ -1,53 +1,55 @@
/*
                This file is part of the Opie Project
-
-              Copyright (C) 2003 Michael 'Mickey' Lauer <mickey@tm.informatik.uni-frankfurt.de>
+              Copyright (C) 2003 Michael 'Mickey' Lauer <mickey@Vanille.de>
=.
.=l.
           .>+-=
 _;:,     .>    :=|. This program is free software; you can
.> <`_,   >  .   <= redistribute it and/or modify it under
:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
.="- .-=="i,     .._ License as published by the Free Software
 - .   .-<_>     .<> Foundation; either version 2 of the License,
     ._= =}       : or (at your option) any later version.
    .%`+i>       _;_.
    .i_,=:_.      -<s. 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
..}^=.=       =       ; Library General Public License for more
++=   -.     .`     .: details.
 :     =  ...= . :.=-
 -.   .:....=;==+<; You should have received a copy of the GNU
  -_. . .   )=.  = Library General Public License along with
    --        :-=` this library; see the file COPYING.LIB.
If not, write to the Free Software Foundation,
Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
*/
#include <opie2/odialog.h>
-int ODialog::mMarginSize = 5; // 11 like in KDialog is probably too much for PDA
-int ODialog::mSpacingSize = 2; // 6 like in KDialog is probably too much for PDA
+#warning Make Margin and Spacing device dependend and configurable!
+
+int ODialog::mMarginSize = 5;
+int ODialog::mSpacingSize = 2;
ODialog::ODialog(QWidget *parent, const char *name, bool modal, WFlags f)
: QDialog(parent, name, modal, f)
{
+ // d = new ODialogPrivate();
}
int ODialog::marginHint()
{
return( mMarginSize );
}
int ODialog::spacingHint()
{
return( mSpacingSize );
}
// Placeholder for even more sophisticed things
diff --git a/libopie2/opieui/odialog.h b/libopie2/opieui/odialog.h
index 4116ed7..ceff612 100644
--- a/libopie2/opieui/odialog.h
+++ b/libopie2/opieui/odialog.h
@@ -1,89 +1,91 @@
/*
                This file is part of the Opie Project
-
-              (C) 2003 Michael 'Mickey' Lauer <mickey@tm.informatik.uni-frankfurt.de>
+              (C) 2003 Michael 'Mickey' Lauer <mickey@Vanille.de>
=.
.=l.
           .>+-=
 _;:,     .>    :=|. This program is free software; you can
.> <`_,   >  .   <= redistribute it and/or modify it under
:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
.="- .-=="i,     .._ License as published by the Free Software
 - .   .-<_>     .<> Foundation; either version 2 of the License,
     ._= =}       : or (at your option) any later version.
    .%`+i>       _;_.
    .i_,=:_.      -<s. 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
..}^=.=       =       ; Library General Public License for more
++=   -.     .`     .: details.
 :     =  ...= . :.=-
 -.   .:....=;==+<; You should have received a copy of the GNU
  -_. . .   )=.  = Library General Public License along with
    --        :-=` this library; see the file COPYING.LIB.
If not, write to the Free Software Foundation,
Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
*/
#ifndef ODIALOG_H
#define ODIALOG_H
class QLayoutItem;
#include <qdialog.h>
/**
* Dialog with extended nonmodal support and methods for OPIE standard
* compliance.
*
* The @ref marginHint() and @ref spacingHint() sizes shall be used
* whenever you layout the interior of a dialog. One special note. If
* you make your own action buttons (OK, Cancel etc), the space
* beteween the buttons shall be @ref spacingHint(), whereas the space
* above, below, to the right and to the left shall be @ref marginHint().
* If you add a separator line above the buttons, there shall be a
* @ref marginHint() between the buttons and the separator and a
* @ref marginHint() above the separator as well.
*
- * @author Michael 'Mickey' Lauer <mickey@tm.informatik.uni-frankfurt.de>
+ * @author Michael 'Mickey' Lauer <mickey@Vanille.de>
*/
+
// lets fix up Qt instead! Size does matter. -zecke
+ // while that may be true, reducing maintainance effort for the future does also matter -
+ // and I believe that maintaining a patch against QtE is more work than our classes -mml
class ODialog : public QDialog
{
Q_OBJECT
public:
/**
* Constructor.
*
* Takes the same arguments as @ref QDialog.
*/
ODialog(QWidget *parent = 0, const char *name = 0, bool modal = false, WFlags f = 0);
/**
* Return the number of pixels you shall use between a
* dialog edge and the outermost widget(s) according to the KDE standard.
**/
static int marginHint();
/**
* Return the number of pixels you shall use between
* widgets inside a dialog according to the KDE standard.
*/
static int spacingHint();
private:
static int mMarginSize;
static int mSpacingSize;
class ODialogPrivate;
- ODialogPrivate *d; // d pointer always needed! -zecke
+ ODialogPrivate *d;
};
#endif // ODIALOG_H
diff --git a/libopie2/opieui/oimageeffect.cpp b/libopie2/opieui/oimageeffect.cpp
index 01e7c6f..9a58bb9 100644
--- a/libopie2/opieui/oimageeffect.cpp
+++ b/libopie2/opieui/oimageeffect.cpp
@@ -1,3587 +1,3588 @@
/* This file is part of the KDE libraries
Copyright (C) 1998, 1999, 2001, 2002 Daniel M. Duley <mosfet@kde.org>
(C) 1998, 1999 Christian Tibirna <ctibirna@total.net>
(C) 1998, 1999 Dirk A. Mueller <mueller@kde.org>
(C) 2000 Josef Weidendorfer <weidendo@in.tum.de>
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.
*/
// $Id$
#include <math.h>
#include <qimage.h>
#include <stdlib.h>
-#include "oimageeffect.h"
+#include <opie2/oimageeffect.h>
+#include <opie2/odebug.h>
#define MaxRGB 255L
#define DegreesToRadians(x) ((x)*M_PI/180.0)
using namespace std;
inline unsigned int intensityValue(unsigned int color)
{
return((unsigned int)((0.299*qRed(color) +
0.587*qGreen(color) +
0.1140000000000001*qBlue(color))));
}
//======================================================================
//
// Gradient effects
//
//======================================================================
QImage OImageEffect::gradient(const QSize &size, const QColor &ca,
const QColor &cb, GradientType eff, int ncols)
{
int rDiff, gDiff, bDiff;
int rca, gca, bca, rcb, gcb, bcb;
QImage image(size, 32);
if (size.width() == 0 || size.height() == 0) {
- qDebug( "WARNING: OImageEffect::gradient: invalid image" );
+ odebug << "WARNING: OImageEffect::gradient: invalid image" << oendl;
return image;
}
register int x, y;
rDiff = (rcb = cb.red()) - (rca = ca.red());
gDiff = (gcb = cb.green()) - (gca = ca.green());
bDiff = (bcb = cb.blue()) - (bca = ca.blue());
if( eff == VerticalGradient || eff == HorizontalGradient ){
uint *p;
uint rgb;
register int rl = rca << 16;
register int gl = gca << 16;
register int bl = bca << 16;
if( eff == VerticalGradient ) {
int rcdelta = ((1<<16) / size.height()) * rDiff;
int gcdelta = ((1<<16) / size.height()) * gDiff;
int bcdelta = ((1<<16) / size.height()) * bDiff;
for ( y = 0; y < size.height(); y++ ) {
p = (uint *) image.scanLine(y);
rl += rcdelta;
gl += gcdelta;
bl += bcdelta;
rgb = qRgb( (rl>>16), (gl>>16), (bl>>16) );
for( x = 0; x < size.width(); x++ ) {
*p = rgb;
p++;
}
}
}
else { // must be HorizontalGradient
unsigned int *o_src = (unsigned int *)image.scanLine(0);
unsigned int *src = o_src;
int rcdelta = ((1<<16) / size.width()) * rDiff;
int gcdelta = ((1<<16) / size.width()) * gDiff;
int bcdelta = ((1<<16) / size.width()) * bDiff;
for( x = 0; x < size.width(); x++) {
rl += rcdelta;
gl += gcdelta;
bl += bcdelta;
*src++ = qRgb( (rl>>16), (gl>>16), (bl>>16));
}
src = o_src;
// Believe it or not, manually copying in a for loop is faster
// than calling memcpy for each scanline (on the order of ms...).
// I think this is due to the function call overhead (mosfet).
for (y = 1; y < size.height(); ++y) {
p = (unsigned int *)image.scanLine(y);
src = o_src;
for(x=0; x < size.width(); ++x)
*p++ = *src++;
}
}
}
else {
float rfd, gfd, bfd;
float rd = rca, gd = gca, bd = bca;
unsigned char *xtable[3];
unsigned char *ytable[3];
unsigned int w = size.width(), h = size.height();
xtable[0] = new unsigned char[w];
xtable[1] = new unsigned char[w];
xtable[2] = new unsigned char[w];
ytable[0] = new unsigned char[h];
ytable[1] = new unsigned char[h];
ytable[2] = new unsigned char[h];
w*=2, h*=2;
if ( eff == DiagonalGradient || eff == CrossDiagonalGradient) {
// Diagonal dgradient code inspired by BlackBox (mosfet)
// BlackBox dgradient is (C) Brad Hughes, <bhughes@tcac.net> and
// Mike Cole <mike@mydot.com>.
rfd = (float)rDiff/w;
gfd = (float)gDiff/w;
bfd = (float)bDiff/w;
int dir;
for (x = 0; x < size.width(); x++, rd+=rfd, gd+=gfd, bd+=bfd) {
dir = eff == DiagonalGradient? x : size.width() - x - 1;
xtable[0][dir] = (unsigned char) rd;
xtable[1][dir] = (unsigned char) gd;
xtable[2][dir] = (unsigned char) bd;
}
rfd = (float)rDiff/h;
gfd = (float)gDiff/h;
bfd = (float)bDiff/h;
rd = gd = bd = 0;
for (y = 0; y < size.height(); y++, rd+=rfd, gd+=gfd, bd+=bfd) {
ytable[0][y] = (unsigned char) rd;
ytable[1][y] = (unsigned char) gd;
ytable[2][y] = (unsigned char) bd;
}
for (y = 0; y < size.height(); y++) {
unsigned int *scanline = (unsigned int *)image.scanLine(y);
for (x = 0; x < size.width(); x++) {
scanline[x] = qRgb(xtable[0][x] + ytable[0][y],
xtable[1][x] + ytable[1][y],
xtable[2][x] + ytable[2][y]);
}
}
}
else if (eff == RectangleGradient ||
eff == PyramidGradient ||
eff == PipeCrossGradient ||
eff == EllipticGradient)
{
int rSign = rDiff>0? 1: -1;
int gSign = gDiff>0? 1: -1;
int bSign = bDiff>0? 1: -1;
rfd = (float)rDiff / size.width();
gfd = (float)gDiff / size.width();
bfd = (float)bDiff / size.width();
rd = (float)rDiff/2;
gd = (float)gDiff/2;
bd = (float)bDiff/2;
for (x = 0; x < size.width(); x++, rd-=rfd, gd-=gfd, bd-=bfd)
{
xtable[0][x] = (unsigned char) abs((int)rd);
xtable[1][x] = (unsigned char) abs((int)gd);
xtable[2][x] = (unsigned char) abs((int)bd);
}
rfd = (float)rDiff/size.height();
gfd = (float)gDiff/size.height();
bfd = (float)bDiff/size.height();
rd = (float)rDiff/2;
gd = (float)gDiff/2;
bd = (float)bDiff/2;
for (y = 0; y < size.height(); y++, rd-=rfd, gd-=gfd, bd-=bfd)
{
ytable[0][y] = (unsigned char) abs((int)rd);
ytable[1][y] = (unsigned char) abs((int)gd);
ytable[2][y] = (unsigned char) abs((int)bd);
}
unsigned int rgb;
int h = (size.height()+1)>>1;
for (y = 0; y < h; y++) {
unsigned int *sl1 = (unsigned int *)image.scanLine(y);
unsigned int *sl2 = (unsigned int *)image.scanLine(QMAX(size.height()-y-1, y));
int w = (size.width()+1)>>1;
int x2 = size.width()-1;
for (x = 0; x < w; x++, x2--) {
rgb = 0;
if (eff == PyramidGradient) {
rgb = qRgb(rcb-rSign*(xtable[0][x]+ytable[0][y]),
gcb-gSign*(xtable[1][x]+ytable[1][y]),
bcb-bSign*(xtable[2][x]+ytable[2][y]));
}
if (eff == RectangleGradient) {
rgb = qRgb(rcb - rSign *
QMAX(xtable[0][x], ytable[0][y]) * 2,
gcb - gSign *
QMAX(xtable[1][x], ytable[1][y]) * 2,
bcb - bSign *
QMAX(xtable[2][x], ytable[2][y]) * 2);
}
if (eff == PipeCrossGradient) {
rgb = qRgb(rcb - rSign *
QMIN(xtable[0][x], ytable[0][y]) * 2,
gcb - gSign *
QMIN(xtable[1][x], ytable[1][y]) * 2,
bcb - bSign *
QMIN(xtable[2][x], ytable[2][y]) * 2);
}
if (eff == EllipticGradient) {
rgb = qRgb(rcb - rSign *
(int)sqrt((xtable[0][x]*xtable[0][x] +
ytable[0][y]*ytable[0][y])*2.0),
gcb - gSign *
(int)sqrt((xtable[1][x]*xtable[1][x] +
ytable[1][y]*ytable[1][y])*2.0),
bcb - bSign *
(int)sqrt((xtable[2][x]*xtable[2][x] +
ytable[2][y]*ytable[2][y])*2.0));
}
sl1[x] = sl2[x] = rgb;
sl1[x2] = sl2[x2] = rgb;
}
}
}
delete [] xtable[0];
delete [] xtable[1];
delete [] xtable[2];
delete [] ytable[0];
delete [] ytable[1];
delete [] ytable[2];
}
// dither if necessary
if (ncols && (QPixmap::defaultDepth() < 15 )) {
if ( ncols < 2 || ncols > 256 )
ncols = 3;
QColor *dPal = new QColor[ncols];
for (int i=0; i<ncols; i++) {
dPal[i].setRgb ( rca + rDiff * i / ( ncols - 1 ),
gca + gDiff * i / ( ncols - 1 ),
bca + bDiff * i / ( ncols - 1 ) );
}
dither(image, dPal, ncols);
delete [] dPal;
}
return image;
}
// -----------------------------------------------------------------------------
//CT this was (before Dirk A. Mueller's speedup changes)
// merely the same code as in the above method, but it's supposedly
// way less performant since it introduces a lot of supplementary tests
// and simple math operations for the calculus of the balance.
// (surprizingly, it isn't less performant, in the contrary :-)
// Yes, I could have merged them, but then the excellent performance of
// the balanced code would suffer with no other gain than a mere
// source code and byte code size economy.
QImage OImageEffect::unbalancedGradient(const QSize &size, const QColor &ca,
const QColor &cb, GradientType eff, int xfactor, int yfactor,
int ncols)
{
int dir; // general parameter used for direction switches
bool _xanti = false , _yanti = false;
if (xfactor < 0) _xanti = true; // negative on X direction
if (yfactor < 0) _yanti = true; // negative on Y direction
xfactor = abs(xfactor);
yfactor = abs(yfactor);
if (!xfactor) xfactor = 1;
if (!yfactor) yfactor = 1;
if (xfactor > 200 ) xfactor = 200;
if (yfactor > 200 ) yfactor = 200;
// float xbal = xfactor/5000.;
// float ybal = yfactor/5000.;
float xbal = xfactor/30./size.width();
float ybal = yfactor/30./size.height();
float rat;
int rDiff, gDiff, bDiff;
int rca, gca, bca, rcb, gcb, bcb;
QImage image(size, 32);
if (size.width() == 0 || size.height() == 0) {
- qDebug( "WARNING: OImageEffect::unbalancedGradient : invalid image" );
+ odebug << "WARNING: OImageEffect::unbalancedGradient : invalid image" << oendl;
return image;
}
register int x, y;
unsigned int *scanline;
rDiff = (rcb = cb.red()) - (rca = ca.red());
gDiff = (gcb = cb.green()) - (gca = ca.green());
bDiff = (bcb = cb.blue()) - (bca = ca.blue());
if( eff == VerticalGradient || eff == HorizontalGradient){
QColor cRow;
uint *p;
uint rgbRow;
if( eff == VerticalGradient) {
for ( y = 0; y < size.height(); y++ ) {
dir = _yanti ? y : size.height() - 1 - y;
p = (uint *) image.scanLine(dir);
rat = 1 - exp( - (float)y * ybal );
cRow.setRgb( rcb - (int) ( rDiff * rat ),
gcb - (int) ( gDiff * rat ),
bcb - (int) ( bDiff * rat ) );
rgbRow = cRow.rgb();
for( x = 0; x < size.width(); x++ ) {
*p = rgbRow;
p++;
}
}
}
else {
unsigned int *src = (unsigned int *)image.scanLine(0);
for(x = 0; x < size.width(); x++ )
{
dir = _xanti ? x : size.width() - 1 - x;
rat = 1 - exp( - (float)x * xbal );
src[dir] = qRgb(rcb - (int) ( rDiff * rat ),
gcb - (int) ( gDiff * rat ),
bcb - (int) ( bDiff * rat ));
}
// Believe it or not, manually copying in a for loop is faster
// than calling memcpy for each scanline (on the order of ms...).
// I think this is due to the function call overhead (mosfet).
for(y = 1; y < size.height(); ++y)
{
scanline = (unsigned int *)image.scanLine(y);
for(x=0; x < size.width(); ++x)
scanline[x] = src[x];
}
}
}
else {
int w=size.width(), h=size.height();
unsigned char *xtable[3];
unsigned char *ytable[3];
xtable[0] = new unsigned char[w];
xtable[1] = new unsigned char[w];
xtable[2] = new unsigned char[w];
ytable[0] = new unsigned char[h];
ytable[1] = new unsigned char[h];
ytable[2] = new unsigned char[h];
if ( eff == DiagonalGradient || eff == CrossDiagonalGradient)
{
for (x = 0; x < w; x++) {
dir = _xanti ? x : w - 1 - x;
rat = 1 - exp( - (float)x * xbal );
xtable[0][dir] = (unsigned char) ( rDiff/2 * rat );
xtable[1][dir] = (unsigned char) ( gDiff/2 * rat );
xtable[2][dir] = (unsigned char) ( bDiff/2 * rat );
}
for (y = 0; y < h; y++) {
dir = _yanti ? y : h - 1 - y;
rat = 1 - exp( - (float)y * ybal );
ytable[0][dir] = (unsigned char) ( rDiff/2 * rat );
ytable[1][dir] = (unsigned char) ( gDiff/2 * rat );
ytable[2][dir] = (unsigned char) ( bDiff/2 * rat );
}
for (y = 0; y < h; y++) {
unsigned int *scanline = (unsigned int *)image.scanLine(y);
for (x = 0; x < w; x++) {
scanline[x] = qRgb(rcb - (xtable[0][x] + ytable[0][y]),
gcb - (xtable[1][x] + ytable[1][y]),
bcb - (xtable[2][x] + ytable[2][y]));
}
}
}
else if (eff == RectangleGradient ||
eff == PyramidGradient ||
eff == PipeCrossGradient ||
eff == EllipticGradient)
{
int rSign = rDiff>0? 1: -1;
int gSign = gDiff>0? 1: -1;
int bSign = bDiff>0? 1: -1;
for (x = 0; x < w; x++)
{
dir = _xanti ? x : w - 1 - x;
rat = 1 - exp( - (float)x * xbal );
xtable[0][dir] = (unsigned char) abs((int)(rDiff*(0.5-rat)));
xtable[1][dir] = (unsigned char) abs((int)(gDiff*(0.5-rat)));
xtable[2][dir] = (unsigned char) abs((int)(bDiff*(0.5-rat)));
}
for (y = 0; y < h; y++)
{
dir = _yanti ? y : h - 1 - y;
rat = 1 - exp( - (float)y * ybal );
ytable[0][dir] = (unsigned char) abs((int)(rDiff*(0.5-rat)));
ytable[1][dir] = (unsigned char) abs((int)(gDiff*(0.5-rat)));
ytable[2][dir] = (unsigned char) abs((int)(bDiff*(0.5-rat)));
}
for (y = 0; y < h; y++) {
unsigned int *scanline = (unsigned int *)image.scanLine(y);
for (x = 0; x < w; x++) {
if (eff == PyramidGradient)
{
scanline[x] = qRgb(rcb-rSign*(xtable[0][x]+ytable[0][y]),
gcb-gSign*(xtable[1][x]+ytable[1][y]),
bcb-bSign*(xtable[2][x]+ytable[2][y]));
}
if (eff == RectangleGradient)
{
scanline[x] = qRgb(rcb - rSign *
QMAX(xtable[0][x], ytable[0][y]) * 2,
gcb - gSign *
QMAX(xtable[1][x], ytable[1][y]) * 2,
bcb - bSign *
QMAX(xtable[2][x], ytable[2][y]) * 2);
}
if (eff == PipeCrossGradient)
{
scanline[x] = qRgb(rcb - rSign *
QMIN(xtable[0][x], ytable[0][y]) * 2,
gcb - gSign *
QMIN(xtable[1][x], ytable[1][y]) * 2,
bcb - bSign *
QMIN(xtable[2][x], ytable[2][y]) * 2);
}
if (eff == EllipticGradient)
{
scanline[x] = qRgb(rcb - rSign *
(int)sqrt((xtable[0][x]*xtable[0][x] +
ytable[0][y]*ytable[0][y])*2.0),
gcb - gSign *
(int)sqrt((xtable[1][x]*xtable[1][x] +
ytable[1][y]*ytable[1][y])*2.0),
bcb - bSign *
(int)sqrt((xtable[2][x]*xtable[2][x] +
ytable[2][y]*ytable[2][y])*2.0));
}
}
}
}
if (ncols && (QPixmap::defaultDepth() < 15 )) {
if ( ncols < 2 || ncols > 256 )
ncols = 3;
QColor *dPal = new QColor[ncols];
for (int i=0; i<ncols; i++) {
dPal[i].setRgb ( rca + rDiff * i / ( ncols - 1 ),
gca + gDiff * i / ( ncols - 1 ),
bca + bDiff * i / ( ncols - 1 ) );
}
dither(image, dPal, ncols);
delete [] dPal;
}
delete [] xtable[0];
delete [] xtable[1];
delete [] xtable[2];
delete [] ytable[0];
delete [] ytable[1];
delete [] ytable[2];
}
return image;
}
//======================================================================
//
// Intensity effects
//
//======================================================================
/* This builds a 256 byte unsigned char lookup table with all
* the possible percent values prior to applying the effect, then uses
* integer math for the pixels. For any image larger than 9x9 this will be
* less expensive than doing a float operation on the 3 color components of
* each pixel. (mosfet)
*/
QImage& OImageEffect::intensity(QImage &image, float percent)
{
if (image.width() == 0 || image.height() == 0) {
- qDebug( "WARNING: OImageEffect::intensity : invalid image" );
+ odebug << "WARNING: OImageEffect::intensity : invalid image" << oendl;
return image;
}
int segColors = image.depth() > 8 ? 256 : image.numColors();
unsigned char *segTbl = new unsigned char[segColors];
int pixels = image.depth() > 8 ? image.width()*image.height() :
image.numColors();
unsigned int *data = image.depth() > 8 ? (unsigned int *)image.bits() :
(unsigned int *)image.colorTable();
bool brighten = (percent >= 0);
if(percent < 0)
percent = -percent;
if(brighten){ // keep overflow check out of loops
for(int i=0; i < segColors; ++i){
int tmp = (int)(i*percent);
if(tmp > 255)
tmp = 255;
segTbl[i] = tmp;
}
}
else{
for(int i=0; i < segColors; ++i){
int tmp = (int)(i*percent);
if(tmp < 0)
tmp = 0;
segTbl[i] = tmp;
}
}
if(brighten){ // same here
for(int i=0; i < pixels; ++i){
int r = qRed(data[i]);
int g = qGreen(data[i]);
int b = qBlue(data[i]);
int a = qAlpha(data[i]);
r = r + segTbl[r] > 255 ? 255 : r + segTbl[r];
g = g + segTbl[g] > 255 ? 255 : g + segTbl[g];
b = b + segTbl[b] > 255 ? 255 : b + segTbl[b];
data[i] = qRgba(r, g, b,a);
}
}
else{
for(int i=0; i < pixels; ++i){
int r = qRed(data[i]);
int g = qGreen(data[i]);
int b = qBlue(data[i]);
int a = qAlpha(data[i]);
r = r - segTbl[r] < 0 ? 0 : r - segTbl[r];
g = g - segTbl[g] < 0 ? 0 : g - segTbl[g];
b = b - segTbl[b] < 0 ? 0 : b - segTbl[b];
data[i] = qRgba(r, g, b, a);
}
}
delete [] segTbl;
return image;
}
QImage& OImageEffect::channelIntensity(QImage &image, float percent,
RGBComponent channel)
{
if (image.width() == 0 || image.height() == 0) {
- qDebug( "WARNING: OImageEffect::channelIntensity : invalid image" );
+ odebug << "WARNING: OImageEffect::channelIntensity : invalid image" << oendl;
return image;
}
int segColors = image.depth() > 8 ? 256 : image.numColors();
unsigned char *segTbl = new unsigned char[segColors];
int pixels = image.depth() > 8 ? image.width()*image.height() :
image.numColors();
unsigned int *data = image.depth() > 8 ? (unsigned int *)image.bits() :
(unsigned int *)image.colorTable();
bool brighten = (percent >= 0);
if(percent < 0)
percent = -percent;
if(brighten){ // keep overflow check out of loops
for(int i=0; i < segColors; ++i){
int tmp = (int)(i*percent);
if(tmp > 255)
tmp = 255;
segTbl[i] = tmp;
}
}
else{
for(int i=0; i < segColors; ++i){
int tmp = (int)(i*percent);
if(tmp < 0)
tmp = 0;
segTbl[i] = tmp;
}
}
if(brighten){ // same here
if(channel == Red){ // and here ;-)
for(int i=0; i < pixels; ++i){
int c = qRed(data[i]);
c = c + segTbl[c] > 255 ? 255 : c + segTbl[c];
data[i] = qRgba(c, qGreen(data[i]), qBlue(data[i]), qAlpha(data[i]));
}
}
if(channel == Green){
for(int i=0; i < pixels; ++i){
int c = qGreen(data[i]);
c = c + segTbl[c] > 255 ? 255 : c + segTbl[c];
data[i] = qRgba(qRed(data[i]), c, qBlue(data[i]), qAlpha(data[i]));
}
}
else{
for(int i=0; i < pixels; ++i){
int c = qBlue(data[i]);
c = c + segTbl[c] > 255 ? 255 : c + segTbl[c];
data[i] = qRgba(qRed(data[i]), qGreen(data[i]), c, qAlpha(data[i]));
}
}
}
else{
if(channel == Red){
for(int i=0; i < pixels; ++i){
int c = qRed(data[i]);
c = c - segTbl[c] < 0 ? 0 : c - segTbl[c];
data[i] = qRgba(c, qGreen(data[i]), qBlue(data[i]), qAlpha(data[i]));
}
}
if(channel == Green){
for(int i=0; i < pixels; ++i){
int c = qGreen(data[i]);
c = c - segTbl[c] < 0 ? 0 : c - segTbl[c];
data[i] = qRgba(qRed(data[i]), c, qBlue(data[i]), qAlpha(data[i]));
}
}
else{
for(int i=0; i < pixels; ++i){
int c = qBlue(data[i]);
c = c - segTbl[c] < 0 ? 0 : c - segTbl[c];
data[i] = qRgba(qRed(data[i]), qGreen(data[i]), c, qAlpha(data[i]));
}
}
}
delete [] segTbl;
return image;
}
// Modulate an image with an RBG channel of another image
//
QImage& OImageEffect::modulate(QImage &image, QImage &modImage, bool reverse,
ModulationType type, int factor, RGBComponent channel)
{
if (image.width() == 0 || image.height() == 0 ||
modImage.width() == 0 || modImage.height() == 0) {
- qDebug( "WARNING: OImageEffect::modulate : invalid image" );
+ odebug << "WARNING: OImageEffect::modulate : invalid image" << oendl;
return image;
}
int r, g, b, h, s, v, a;
QColor clr;
int mod=0;
unsigned int x1, x2, y1, y2;
register int x, y;
// for image, we handle only depth 32
if (image.depth()<32) image = image.convertDepth(32);
// for modImage, we handle depth 8 and 32
if (modImage.depth()<8) modImage = modImage.convertDepth(8);
unsigned int *colorTable2 = (modImage.depth()==8) ?
modImage.colorTable():0;
unsigned int *data1, *data2;
unsigned char *data2b;
unsigned int color1, color2;
x1 = image.width(); y1 = image.height();
x2 = modImage.width(); y2 = modImage.height();
for (y = 0; y < (int)y1; y++) {
data1 = (unsigned int *) image.scanLine(y);
data2 = (unsigned int *) modImage.scanLine( y%y2 );
data2b = (unsigned char *) modImage.scanLine( y%y2 );
x=0;
while(x < (int)x1) {
color2 = (colorTable2) ? colorTable2[*data2b] : *data2;
if (reverse) {
color1 = color2;
color2 = *data1;
}
else
color1 = *data1;
if (type == Intensity || type == Contrast) {
r = qRed(color1);
g = qGreen(color1);
b = qBlue(color1);
if (channel != All) {
mod = (channel == Red) ? qRed(color2) :
(channel == Green) ? qGreen(color2) :
(channel == Blue) ? qBlue(color2) :
(channel == Gray) ? qGray(color2) : 0;
mod = mod*factor/50;
}
if (type == Intensity) {
if (channel == All) {
r += r * factor/50 * qRed(color2)/256;
g += g * factor/50 * qGreen(color2)/256;
b += b * factor/50 * qBlue(color2)/256;
}
else {
r += r * mod/256;
g += g * mod/256;
b += b * mod/256;
}
}
else { // Contrast
if (channel == All) {
r += (r-128) * factor/50 * qRed(color2)/128;
g += (g-128) * factor/50 * qGreen(color2)/128;
b += (b-128) * factor/50 * qBlue(color2)/128;
}
else {
r += (r-128) * mod/128;
g += (g-128) * mod/128;
b += (b-128) * mod/128;
}
}
if (r<0) r=0; if (r>255) r=255;
if (g<0) g=0; if (g>255) g=255;
if (b<0) b=0; if (b>255) b=255;
a = qAlpha(*data1);
*data1 = qRgba(r, g, b, a);
}
else if (type == Saturation || type == HueShift) {
clr.setRgb(color1);
clr.hsv(&h, &s, &v);
mod = (channel == Red) ? qRed(color2) :
(channel == Green) ? qGreen(color2) :
(channel == Blue) ? qBlue(color2) :
(channel == Gray) ? qGray(color2) : 0;
mod = mod*factor/50;
if (type == Saturation) {
s -= s * mod/256;
if (s<0) s=0; if (s>255) s=255;
}
else { // HueShift
h += mod;
while(h<0) h+=360;
h %= 360;
}
clr.setHsv(h, s, v);
a = qAlpha(*data1);
*data1 = clr.rgb() | ((uint)(a & 0xff) << 24);
}
data1++; data2++; data2b++; x++;
if ( (x%x2) ==0) { data2 -= x2; data2b -= x2; }
}
}
return image;
}
//======================================================================
//
// Blend effects
//
//======================================================================
// Nice and fast direct pixel manipulation
QImage& OImageEffect::blend(const QColor& clr, QImage& dst, float opacity)
{
if (dst.width() <= 0 || dst.height() <= 0)
return dst;
if (opacity < 0.0 || opacity > 1.0) {
- qDebug( "WARNING: OImageEffect::blend : invalid opacity. Range [0, 1] ");
+ odebug << "WARNING: OImageEffect::blend : invalid opacity. Range [0, 1] " << oendl;
return dst;
}
int depth = dst.depth();
if (depth != 32)
dst = dst.convertDepth(32);
int pixels = dst.width() * dst.height();
int rcol, gcol, bcol;
clr.rgb(&rcol, &gcol, &bcol);
#ifdef WORDS_BIGENDIAN // ARGB (skip alpha)
register unsigned char *data = (unsigned char *)dst.bits() + 1;
#else // BGRA
register unsigned char *data = (unsigned char *)dst.bits();
#endif
for (register int i=0; i<pixels; i++)
{
#ifdef WORDS_BIGENDIAN
*(data++) += (unsigned char)((rcol - *data) * opacity);
*(data++) += (unsigned char)((gcol - *data) * opacity);
*(data++) += (unsigned char)((bcol - *data) * opacity);
#else
*(data++) += (unsigned char)((bcol - *data) * opacity);
*(data++) += (unsigned char)((gcol - *data) * opacity);
*(data++) += (unsigned char)((rcol - *data) * opacity);
#endif
data++; // skip alpha
}
return dst;
}
// Nice and fast direct pixel manipulation
QImage& OImageEffect::blend(QImage& src, QImage& dst, float opacity)
{
if (src.width() <= 0 || src.height() <= 0)
return dst;
if (dst.width() <= 0 || dst.height() <= 0)
return dst;
if (src.width() != dst.width() || src.height() != dst.height()) {
- qDebug( "WARNING: OImageEffect::blend : src and destination images are not the same size" );
+ odebug << "WARNING: OImageEffect::blend : src and destination images are not the same size" << oendl;
return dst;
}
if (opacity < 0.0 || opacity > 1.0) {
- qDebug( "WARNING: OImageEffect::blend : invalid opacity. Range [0, 1]" );
+ odebug << "WARNING: OImageEffect::blend : invalid opacity. Range [0, 1]" << oendl;
return dst;
}
if (src.depth() != 32) src = src.convertDepth(32);
if (dst.depth() != 32) dst = dst.convertDepth(32);
int pixels = src.width() * src.height();
#ifdef WORDS_BIGENDIAN // ARGB (skip alpha)
register unsigned char *data1 = (unsigned char *)dst.bits() + 1;
register unsigned char *data2 = (unsigned char *)src.bits() + 1;
#else // BGRA
register unsigned char *data1 = (unsigned char *)dst.bits();
register unsigned char *data2 = (unsigned char *)src.bits();
#endif
for (register int i=0; i<pixels; i++)
{
#ifdef WORDS_BIGENDIAN
*(data1++) += (unsigned char)((*(data2++) - *data1) * opacity);
*(data1++) += (unsigned char)((*(data2++) - *data1) * opacity);
*(data1++) += (unsigned char)((*(data2++) - *data1) * opacity);
#else
*(data1++) += (unsigned char)((*(data2++) - *data1) * opacity);
*(data1++) += (unsigned char)((*(data2++) - *data1) * opacity);
*(data1++) += (unsigned char)((*(data2++) - *data1) * opacity);
#endif
data1++; // skip alpha
data2++;
}
return dst;
}
QImage& OImageEffect::blend(QImage &image, float initial_intensity,
const QColor &bgnd, GradientType eff,
bool anti_dir)
{
if (image.width() == 0 || image.height() == 0 || image.depth()!=32 ) {
- qDebug( "WARNING: OImageEffect::blend : invalid image" );
+ odebug << "WARNING: OImageEffect::blend : invalid image" << oendl;
return image;
}
int r_bgnd = bgnd.red(), g_bgnd = bgnd.green(), b_bgnd = bgnd.blue();
int r, g, b;
int ind;
unsigned int xi, xf, yi, yf;
unsigned int a;
// check the boundaries of the initial intesity param
float unaffected = 1;
if (initial_intensity > 1) initial_intensity = 1;
if (initial_intensity < -1) initial_intensity = -1;
if (initial_intensity < 0) {
unaffected = 1. + initial_intensity;
initial_intensity = 0;
}
float intensity = initial_intensity;
float var = 1. - initial_intensity;
if (anti_dir) {
initial_intensity = intensity = 1.;
var = -var;
}
register int x, y;
unsigned int *data = (unsigned int *)image.bits();
int image_width = image.width(); //Those can't change
int image_height = image.height();
if( eff == VerticalGradient || eff == HorizontalGradient ) {
// set the image domain to apply the effect to
xi = 0, xf = image_width;
yi = 0, yf = image_height;
if (eff == VerticalGradient) {
if (anti_dir) yf = (int)(image_height * unaffected);
else yi = (int)(image_height * (1 - unaffected));
}
else {
if (anti_dir) xf = (int)(image_width * unaffected);
else xi = (int)(image_height * (1 - unaffected));
}
var /= (eff == VerticalGradient?yf-yi:xf-xi);
int ind_base;
for (y = yi; y < (int)yf; y++) {
intensity = eff == VerticalGradient? intensity + var :
initial_intensity;
ind_base = image_width * y ;
for (x = xi; x < (int)xf ; x++) {
if (eff == HorizontalGradient) intensity += var;
ind = x + ind_base;
r = qRed (data[ind]) + (int)(intensity *
(r_bgnd - qRed (data[ind])));
g = qGreen(data[ind]) + (int)(intensity *
(g_bgnd - qGreen(data[ind])));
b = qBlue (data[ind]) + (int)(intensity *
(b_bgnd - qBlue (data[ind])));
if (r > 255) r = 255; if (r < 0 ) r = 0;
if (g > 255) g = 255; if (g < 0 ) g = 0;
if (b > 255) b = 255; if (b < 0 ) b = 0;
a = qAlpha(data[ind]);
data[ind] = qRgba(r, g, b, a);
}
}
}
else if (eff == DiagonalGradient || eff == CrossDiagonalGradient) {
float xvar = var / 2 / image_width; // / unaffected;
float yvar = var / 2 / image_height; // / unaffected;
float tmp;
for (x = 0; x < image_width ; x++) {
tmp = xvar * (eff == DiagonalGradient? x : image.width()-x-1);
ind = x;
for (y = 0; y < image_height ; y++) {
intensity = initial_intensity + tmp + yvar * y;
r = qRed (data[ind]) + (int)(intensity *
(r_bgnd - qRed (data[ind])));
g = qGreen(data[ind]) + (int)(intensity *
(g_bgnd - qGreen(data[ind])));
b = qBlue (data[ind]) + (int)(intensity *
(b_bgnd - qBlue (data[ind])));
if (r > 255) r = 255; if (r < 0 ) r = 0;
if (g > 255) g = 255; if (g < 0 ) g = 0;
if (b > 255) b = 255; if (b < 0 ) b = 0;
a = qAlpha(data[ind]);
data[ind] = qRgba(r, g, b, a);
ind += image_width;
}
}
}
else if (eff == RectangleGradient || eff == EllipticGradient) {
float xvar;
float yvar;
for (x = 0; x < image_width / 2 + image_width % 2; x++) {
xvar = var / image_width * (image_width - x*2/unaffected-1);
for (y = 0; y < image_height / 2 + image_height % 2; y++) {
yvar = var / image_height * (image_height - y*2/unaffected -1);
if (eff == RectangleGradient)
intensity = initial_intensity + QMAX(xvar, yvar);
else
intensity = initial_intensity + sqrt(xvar * xvar + yvar * yvar);
if (intensity > 1) intensity = 1;
if (intensity < 0) intensity = 0;
//NW
ind = x + image_width * y ;
r = qRed (data[ind]) + (int)(intensity *
(r_bgnd - qRed (data[ind])));
g = qGreen(data[ind]) + (int)(intensity *
(g_bgnd - qGreen(data[ind])));
b = qBlue (data[ind]) + (int)(intensity *
(b_bgnd - qBlue (data[ind])));
if (r > 255) r = 255; if (r < 0 ) r = 0;
if (g > 255) g = 255; if (g < 0 ) g = 0;
if (b > 255) b = 255; if (b < 0 ) b = 0;
a = qAlpha(data[ind]);
data[ind] = qRgba(r, g, b, a);
//NE
ind = image_width - x - 1 + image_width * y ;
r = qRed (data[ind]) + (int)(intensity *
(r_bgnd - qRed (data[ind])));
g = qGreen(data[ind]) + (int)(intensity *
(g_bgnd - qGreen(data[ind])));
b = qBlue (data[ind]) + (int)(intensity *
(b_bgnd - qBlue (data[ind])));
if (r > 255) r = 255; if (r < 0 ) r = 0;
if (g > 255) g = 255; if (g < 0 ) g = 0;
if (b > 255) b = 255; if (b < 0 ) b = 0;
a = qAlpha(data[ind]);
data[ind] = qRgba(r, g, b, a);
}
}
//CT loop is doubled because of stupid central row/column issue.
// other solution?
for (x = 0; x < image_width / 2; x++) {
xvar = var / image_width * (image_width - x*2/unaffected-1);
for (y = 0; y < image_height / 2; y++) {
yvar = var / image_height * (image_height - y*2/unaffected -1);
if (eff == RectangleGradient)
intensity = initial_intensity + QMAX(xvar, yvar);
else
intensity = initial_intensity + sqrt(xvar * xvar + yvar * yvar);
if (intensity > 1) intensity = 1;
if (intensity < 0) intensity = 0;
//SW
ind = x + image_width * (image_height - y -1) ;
r = qRed (data[ind]) + (int)(intensity *
(r_bgnd - qRed (data[ind])));
g = qGreen(data[ind]) + (int)(intensity *
(g_bgnd - qGreen(data[ind])));
b = qBlue (data[ind]) + (int)(intensity *
(b_bgnd - qBlue (data[ind])));
if (r > 255) r = 255; if (r < 0 ) r = 0;
if (g > 255) g = 255; if (g < 0 ) g = 0;
if (b > 255) b = 255; if (b < 0 ) b = 0;
a = qAlpha(data[ind]);
data[ind] = qRgba(r, g, b, a);
//SE
ind = image_width-x-1 + image_width * (image_height - y - 1) ;
r = qRed (data[ind]) + (int)(intensity *
(r_bgnd - qRed (data[ind])));
g = qGreen(data[ind]) + (int)(intensity *
(g_bgnd - qGreen(data[ind])));
b = qBlue (data[ind]) + (int)(intensity *
(b_bgnd - qBlue (data[ind])));
if (r > 255) r = 255; if (r < 0 ) r = 0;
if (g > 255) g = 255; if (g < 0 ) g = 0;
if (b > 255) b = 255; if (b < 0 ) b = 0;
a = qAlpha(data[ind]);
data[ind] = qRgba(r, g, b, a);
}
}
}
- else qDebug( "OImageEffect::blend effect not implemented" );
+ else odebug << "OImageEffect::blend effect not implemented" << oendl;
return image;
}
// Not very efficient as we create a third big image...
//
QImage& OImageEffect::blend(QImage &image1, QImage &image2,
GradientType gt, int xf, int yf)
{
if (image1.width() == 0 || image1.height() == 0 ||
image2.width() == 0 || image2.height() == 0)
return image1;
QImage image3;
image3 = OImageEffect::unbalancedGradient(image1.size(),
QColor(0,0,0), QColor(255,255,255),
gt, xf, yf, 0);
return blend(image1,image2,image3, Red); // Channel to use is arbitrary
}
// Blend image2 into image1, using an RBG channel of blendImage
//
QImage& OImageEffect::blend(QImage &image1, QImage &image2,
QImage &blendImage, RGBComponent channel)
{
if (image1.width() == 0 || image1.height() == 0 ||
image2.width() == 0 || image2.height() == 0 ||
blendImage.width() == 0 || blendImage.height() == 0) {
- qDebug( "OImageEffect::blend effect invalid image" );
+ odebug << "OImageEffect::blend effect invalid image" << oendl;
return image1;
}
int r, g, b;
int ind1, ind2, ind3;
unsigned int x1, x2, x3, y1, y2, y3;
unsigned int a;
register int x, y;
// for image1 and image2, we only handle depth 32
if (image1.depth()<32) image1 = image1.convertDepth(32);
if (image2.depth()<32) image2 = image2.convertDepth(32);
// for blendImage, we handle depth 8 and 32
if (blendImage.depth()<8) blendImage = blendImage.convertDepth(8);
unsigned int *colorTable3 = (blendImage.depth()==8) ?
blendImage.colorTable():0;
unsigned int *data1 = (unsigned int *)image1.bits();
unsigned int *data2 = (unsigned int *)image2.bits();
unsigned int *data3 = (unsigned int *)blendImage.bits();
unsigned char *data3b = (unsigned char *)blendImage.bits();
unsigned int color3;
x1 = image1.width(); y1 = image1.height();
x2 = image2.width(); y2 = image2.height();
x3 = blendImage.width(); y3 = blendImage.height();
for (y = 0; y < (int)y1; y++) {
ind1 = x1*y;
ind2 = x2*(y%y2);
ind3 = x3*(y%y3);
x=0;
while(x < (int)x1) {
color3 = (colorTable3) ? colorTable3[data3b[ind3]] : data3[ind3];
a = (channel == Red) ? qRed(color3) :
(channel == Green) ? qGreen(color3) :
(channel == Blue) ? qBlue(color3) : qGray(color3);
r = (a*qRed(data1[ind1]) + (256-a)*qRed(data2[ind2]))/256;
g = (a*qGreen(data1[ind1]) + (256-a)*qGreen(data2[ind2]))/256;
b = (a*qBlue(data1[ind1]) + (256-a)*qBlue(data2[ind2]))/256;
a = qAlpha(data1[ind1]);
data1[ind1] = qRgba(r, g, b, a);
ind1++; ind2++; ind3++; x++;
if ( (x%x2) ==0) ind2 -= x2;
if ( (x%x3) ==0) ind3 -= x3;
}
}
return image1;
}
//======================================================================
//
// Hash effects
//
//======================================================================
unsigned int OImageEffect::lHash(unsigned int c)
{
unsigned char r = qRed(c), g = qGreen(c), b = qBlue(c), a = qAlpha(c);
unsigned char nr, ng, nb;
nr =(r >> 1) + (r >> 2); nr = nr > r ? 0 : nr;
ng =(g >> 1) + (g >> 2); ng = ng > g ? 0 : ng;
nb =(b >> 1) + (b >> 2); nb = nb > b ? 0 : nb;
return qRgba(nr, ng, nb, a);
}
// -----------------------------------------------------------------------------
unsigned int OImageEffect::uHash(unsigned int c)
{
unsigned char r = qRed(c), g = qGreen(c), b = qBlue(c), a = qAlpha(c);
unsigned char nr, ng, nb;
nr = r + (r >> 3); nr = nr < r ? ~0 : nr;
ng = g + (g >> 3); ng = ng < g ? ~0 : ng;
nb = b + (b >> 3); nb = nb < b ? ~0 : nb;
return qRgba(nr, ng, nb, a);
}
// -----------------------------------------------------------------------------
QImage& OImageEffect::hash(QImage &image, Lighting lite, unsigned int spacing)
{
if (image.width() == 0 || image.height() == 0) {
- qDebug( "OImageEffect::hash effect invalid image" );
+ odebug << "OImageEffect::hash effect invalid image" << oendl;
return image;
}
register int x, y;
unsigned int *data = (unsigned int *)image.bits();
unsigned int ind;
//CT no need to do it if not enough space
if ((lite == NorthLite ||
lite == SouthLite)&&
(unsigned)image.height() < 2+spacing) return image;
if ((lite == EastLite ||
lite == WestLite)&&
(unsigned)image.height() < 2+spacing) return image;
if (lite == NorthLite || lite == SouthLite) {
for (y = 0 ; y < image.height(); y = y + 2 + spacing) {
for (x = 0; x < image.width(); x++) {
ind = x + image.width() * y;
data[ind] = lite==NorthLite?uHash(data[ind]):lHash(data[ind]);
ind = ind + image.width();
data[ind] = lite==NorthLite?lHash(data[ind]):uHash(data[ind]);
}
}
}
else if (lite == EastLite || lite == WestLite) {
for (y = 0 ; y < image.height(); y++) {
for (x = 0; x < image.width(); x = x + 2 + spacing) {
ind = x + image.width() * y;
data[ind] = lite==EastLite?uHash(data[ind]):lHash(data[ind]);
ind++;
data[ind] = lite==EastLite?lHash(data[ind]):uHash(data[ind]);
}
}
}
else if (lite == NWLite || lite == SELite) {
for (y = 0 ; y < image.height(); y++) {
for (x = 0;
x < (int)(image.width() - ((y & 1)? 1 : 0) * spacing);
x = x + 2 + spacing) {
ind = x + image.width() * y + ((y & 1)? 1 : 0);
data[ind] = lite==NWLite?uHash(data[ind]):lHash(data[ind]);
ind++;
data[ind] = lite==NWLite?lHash(data[ind]):uHash(data[ind]);
}
}
}
else if (lite == SWLite || lite == NELite) {
for (y = 0 ; y < image.height(); y++) {
for (x = 0 + ((y & 1)? 1 : 0); x < image.width(); x = x + 2 + spacing) {
ind = x + image.width() * y - ((y & 1)? 1 : 0);
data[ind] = lite==SWLite?uHash(data[ind]):lHash(data[ind]);
ind++;
data[ind] = lite==SWLite?lHash(data[ind]):uHash(data[ind]);
}
}
}
return image;
}
//======================================================================
//
// Flatten effects
//
//======================================================================
QImage& OImageEffect::flatten(QImage &img, const QColor &ca,
const QColor &cb, int ncols)
{
if (img.width() == 0 || img.height() == 0)
return img;
// a bitmap is easy...
if (img.depth() == 1) {
img.setColor(0, ca.rgb());
img.setColor(1, cb.rgb());
return img;
}
int r1 = ca.red(); int r2 = cb.red();
int g1 = ca.green(); int g2 = cb.green();
int b1 = ca.blue(); int b2 = cb.blue();
int min = 0, max = 255;
QRgb col;
// Get minimum and maximum greylevel.
if (img.numColors()) {
// pseudocolor
for (int i = 0; i < img.numColors(); i++) {
col = img.color(i);
int mean = (qRed(col) + qGreen(col) + qBlue(col)) / 3;
min = QMIN(min, mean);
max = QMAX(max, mean);
}
} else {
// truecolor
for (int y=0; y < img.height(); y++)
for (int x=0; x < img.width(); x++) {
col = img.pixel(x, y);
int mean = (qRed(col) + qGreen(col) + qBlue(col)) / 3;
min = QMIN(min, mean);
max = QMAX(max, mean);
}
}
// Conversion factors
float sr = ((float) r2 - r1) / (max - min);
float sg = ((float) g2 - g1) / (max - min);
float sb = ((float) b2 - b1) / (max - min);
// Repaint the image
if (img.numColors()) {
for (int i=0; i < img.numColors(); i++) {
col = img.color(i);
int mean = (qRed(col) + qGreen(col) + qBlue(col)) / 3;
int r = (int) (sr * (mean - min) + r1 + 0.5);
int g = (int) (sg * (mean - min) + g1 + 0.5);
int b = (int) (sb * (mean - min) + b1 + 0.5);
img.setColor(i, qRgba(r, g, b, qAlpha(col)));
}
} else {
for (int y=0; y < img.height(); y++)
for (int x=0; x < img.width(); x++) {
col = img.pixel(x, y);
int mean = (qRed(col) + qGreen(col) + qBlue(col)) / 3;
int r = (int) (sr * (mean - min) + r1 + 0.5);
int g = (int) (sg * (mean - min) + g1 + 0.5);
int b = (int) (sb * (mean - min) + b1 + 0.5);
img.setPixel(x, y, qRgba(r, g, b, qAlpha(col)));
}
}
// Dither if necessary
if ( (ncols <= 0) || ((img.numColors() != 0) && (img.numColors() <= ncols)))
return img;
if (ncols == 1) ncols++;
if (ncols > 256) ncols = 256;
QColor *pal = new QColor[ncols];
sr = ((float) r2 - r1) / (ncols - 1);
sg = ((float) g2 - g1) / (ncols - 1);
sb = ((float) b2 - b1) / (ncols - 1);
for (int i=0; i<ncols; i++)
pal[i] = QColor(r1 + int(sr*i), g1 + int(sg*i), b1 + int(sb*i));
dither(img, pal, ncols);
delete[] pal;
return img;
}
//======================================================================
//
// Fade effects
//
//======================================================================
QImage& OImageEffect::fade(QImage &img, float val, const QColor &color)
{
if (img.width() == 0 || img.height() == 0)
return img;
// We don't handle bitmaps
if (img.depth() == 1)
return img;
unsigned char tbl[256];
for (int i=0; i<256; i++)
tbl[i] = (int) (val * i + 0.5);
int red = color.red();
int green = color.green();
int blue = color.blue();
QRgb col;
int r, g, b, cr, cg, cb;
if (img.depth() <= 8) {
// pseudo color
for (int i=0; i<img.numColors(); i++) {
col = img.color(i);
cr = qRed(col); cg = qGreen(col); cb = qBlue(col);
if (cr > red)
r = cr - tbl[cr - red];
else
r = cr + tbl[red - cr];
if (cg > green)
g = cg - tbl[cg - green];
else
g = cg + tbl[green - cg];
if (cb > blue)
b = cb - tbl[cb - blue];
else
b = cb + tbl[blue - cb];
img.setColor(i, qRgba(r, g, b, qAlpha(col)));
}
} else {
// truecolor
for (int y=0; y<img.height(); y++) {
QRgb *data = (QRgb *) img.scanLine(y);
for (int x=0; x<img.width(); x++) {
col = *data;
cr = qRed(col); cg = qGreen(col); cb = qBlue(col);
if (cr > red)
r = cr - tbl[cr - red];
else
r = cr + tbl[red - cr];
if (cg > green)
g = cg - tbl[cg - green];
else
g = cg + tbl[green - cg];
if (cb > blue)
b = cb - tbl[cb - blue];
else
b = cb + tbl[blue - cb];
*data++ = qRgba(r, g, b, qAlpha(col));
}
}
}
return img;
}
//======================================================================
//
// Color effects
//
//======================================================================
// This code is adapted from code (C) Rik Hemsley <rik@kde.org>
//
// The formula used (r + b + g) /3 is different from the qGray formula
// used by Qt. This is because our formula is much much faster. If,
// however, it turns out that this is producing sub-optimal images,
// then it will have to change (kurt)
//
// It does produce lower quality grayscale ;-) Use fast == true for the fast
// algorithm, false for the higher quality one (mosfet).
QImage& OImageEffect::toGray(QImage &img, bool fast)
{
if (img.width() == 0 || img.height() == 0)
return img;
if(fast){
if (img.depth() == 32) {
register uchar * r(img.bits());
register uchar * g(img.bits() + 1);
register uchar * b(img.bits() + 2);
uchar * end(img.bits() + img.numBytes());
while (r != end) {
*r = *g = *b = (((*r + *g) >> 1) + *b) >> 1; // (r + b + g) / 3
r += 4;
g += 4;
b += 4;
}
}
else
{
for (int i = 0; i < img.numColors(); i++)
{
register uint r = qRed(img.color(i));
register uint g = qGreen(img.color(i));
register uint b = qBlue(img.color(i));
register uint gray = (((r + g) >> 1) + b) >> 1;
img.setColor(i, qRgba(gray, gray, gray, qAlpha(img.color(i))));
}
}
}
else{
int pixels = img.depth() > 8 ? img.width()*img.height() :
img.numColors();
unsigned int *data = img.depth() > 8 ? (unsigned int *)img.bits() :
(unsigned int *)img.colorTable();
int val, i;
for(i=0; i < pixels; ++i){
val = qGray(data[i]);
data[i] = qRgba(val, val, val, qAlpha(data[i]));
}
}
return img;
}
// CT 29Jan2000 - desaturation algorithms
QImage& OImageEffect::desaturate(QImage &img, float desat)
{
if (img.width() == 0 || img.height() == 0)
return img;
if (desat < 0) desat = 0.;
if (desat > 1) desat = 1.;
int pixels = img.depth() > 8 ? img.width()*img.height() :
img.numColors();
unsigned int *data = img.depth() > 8 ? (unsigned int *)img.bits() :
(unsigned int *)img.colorTable();
int h, s, v, i;
QColor clr; // keep constructor out of loop (mosfet)
for(i=0; i < pixels; ++i){
clr.setRgb(data[i]);
clr.hsv(&h, &s, &v);
clr.setHsv(h, (int)(s * (1. - desat)), v);
data[i] = clr.rgb();
}
return img;
}
// Contrast stuff (mosfet)
QImage& OImageEffect::contrast(QImage &img, int c)
{
if (img.width() == 0 || img.height() == 0)
return img;
if(c > 255)
c = 255;
if(c < -255)
c = -255;
int pixels = img.depth() > 8 ? img.width()*img.height() :
img.numColors();
unsigned int *data = img.depth() > 8 ? (unsigned int *)img.bits() :
(unsigned int *)img.colorTable();
int i, r, g, b;
for(i=0; i < pixels; ++i){
r = qRed(data[i]);
g = qGreen(data[i]);
b = qBlue(data[i]);
if(qGray(data[i]) <= 127){
if(r - c <= 255)
r -= c;
if(g - c <= 255)
g -= c;
if(b - c <= 255)
b -= c;
}
else{
if(r + c <= 255)
r += c;
if(g + c <= 255)
g += c;
if(b + c <= 255)
b += c;
}
data[i] = qRgba(r, g, b, qAlpha(data[i]));
}
return(img);
}
//======================================================================
//
// Dithering effects
//
//======================================================================
// adapted from kFSDither (C) 1997 Martin Jones (mjones@kde.org)
//
// Floyd-Steinberg dithering
// Ref: Bitmapped Graphics Programming in C++
// Marv Luse, Addison-Wesley Publishing, 1993.
QImage& OImageEffect::dither(QImage &img, const QColor *palette, int size)
{
if (img.width() == 0 || img.height() == 0 ||
palette == 0 || img.depth() <= 8)
return img;
QImage dImage( img.width(), img.height(), 8, size );
int i;
dImage.setNumColors( size );
for ( i = 0; i < size; i++ )
dImage.setColor( i, palette[ i ].rgb() );
int *rerr1 = new int [ img.width() * 2 ];
int *gerr1 = new int [ img.width() * 2 ];
int *berr1 = new int [ img.width() * 2 ];
memset( rerr1, 0, sizeof( int ) * img.width() * 2 );
memset( gerr1, 0, sizeof( int ) * img.width() * 2 );
memset( berr1, 0, sizeof( int ) * img.width() * 2 );
int *rerr2 = rerr1 + img.width();
int *gerr2 = gerr1 + img.width();
int *berr2 = berr1 + img.width();
for ( int j = 0; j < img.height(); j++ )
{
uint *ip = (uint * )img.scanLine( j );
uchar *dp = dImage.scanLine( j );
for ( i = 0; i < img.width(); i++ )
{
rerr1[i] = rerr2[i] + qRed( *ip );
rerr2[i] = 0;
gerr1[i] = gerr2[i] + qGreen( *ip );
gerr2[i] = 0;
berr1[i] = berr2[i] + qBlue( *ip );
berr2[i] = 0;
ip++;
}
*dp++ = nearestColor( rerr1[0], gerr1[0], berr1[0], palette, size );
for ( i = 1; i < img.width()-1; i++ )
{
int indx = nearestColor( rerr1[i], gerr1[i], berr1[i], palette, size );
*dp = indx;
int rerr = rerr1[i];
rerr -= palette[indx].red();
int gerr = gerr1[i];
gerr -= palette[indx].green();
int berr = berr1[i];
berr -= palette[indx].blue();
// diffuse red error
rerr1[ i+1 ] += ( rerr * 7 ) >> 4;
rerr2[ i-1 ] += ( rerr * 3 ) >> 4;
rerr2[ i ] += ( rerr * 5 ) >> 4;
rerr2[ i+1 ] += ( rerr ) >> 4;
// diffuse green error
gerr1[ i+1 ] += ( gerr * 7 ) >> 4;
gerr2[ i-1 ] += ( gerr * 3 ) >> 4;
gerr2[ i ] += ( gerr * 5 ) >> 4;
gerr2[ i+1 ] += ( gerr ) >> 4;
// diffuse red error
berr1[ i+1 ] += ( berr * 7 ) >> 4;
berr2[ i-1 ] += ( berr * 3 ) >> 4;
berr2[ i ] += ( berr * 5 ) >> 4;
berr2[ i+1 ] += ( berr ) >> 4;
dp++;
}
*dp = nearestColor( rerr1[i], gerr1[i], berr1[i], palette, size );
}
delete [] rerr1;
delete [] gerr1;
delete [] berr1;
img = dImage;
return img;
}
int OImageEffect::nearestColor( int r, int g, int b, const QColor *palette, int size )
{
if (palette == 0)
return 0;
int dr = palette[0].red() - r;
int dg = palette[0].green() - g;
int db = palette[0].blue() - b;
int minDist = dr*dr + dg*dg + db*db;
int nearest = 0;
for (int i = 1; i < size; i++ )
{
dr = palette[i].red() - r;
dg = palette[i].green() - g;
db = palette[i].blue() - b;
int dist = dr*dr + dg*dg + db*db;
if ( dist < minDist )
{
minDist = dist;
nearest = i;
}
}
return nearest;
}
bool OImageEffect::blend(
const QImage & upper,
const QImage & lower,
QImage & output
)
{
if (
upper.width() > lower.width() ||
upper.height() > lower.height() ||
upper.depth() != 32 ||
lower.depth() != 32
)
{
- qDebug( "OImageEffect::blend : Sizes not correct" );
+ odebug << "OImageEffect::blend : Sizes not correct" << oendl;
return false;
}
output = lower.copy();
register uchar *i, *o;
register int a;
register int col;
register int w = upper.width();
int row(upper.height() - 1);
do {
i = upper.scanLine(row);
o = output.scanLine(row);
col = w << 2;
--col;
do {
while (!(a = i[col]) && (col != 3)) {
--col; --col; --col; --col;
}
--col;
o[col] += ((i[col] - o[col]) * a) >> 8;
--col;
o[col] += ((i[col] - o[col]) * a) >> 8;
--col;
o[col] += ((i[col] - o[col]) * a) >> 8;
} while (col--);
} while (row--);
return true;
}
#if 0
// Not yet...
bool OImageEffect::blend(
const QImage & upper,
const QImage & lower,
QImage & output,
const QRect & destRect
)
{
output = lower.copy();
return output;
}
#endif
bool OImageEffect::blend(
int &x, int &y,
const QImage & upper,
const QImage & lower,
QImage & output
)
{
int cx=0, cy=0, cw=upper.width(), ch=upper.height();
if ( upper.width() + x > lower.width() ||
upper.height() + y > lower.height() ||
x < 0 || y < 0 ||
upper.depth() != 32 || lower.depth() != 32 )
{
if ( x > lower.width() || y > lower.height() ) return false;
if ( upper.width()<=0 || upper.height() <= 0 ) return false;
if ( lower.width()<=0 || lower.height() <= 0 ) return false;
if (x<0) {cx=-x; cw+=x; x=0; };
if (cw + x > lower.width()) { cw=lower.width()-x; };
if (y<0) {cy=-y; ch+=y; y=0; };
if (ch + y > lower.height()) { ch=lower.height()-y; };
if ( cx >= upper.width() || cy >= upper.height() ) return true;
if ( cw <= 0 || ch <= 0 ) return true;
}
output.create(cw,ch,32);
// output.setAlphaBuffer(true); // I should do some benchmarks to see if
// this is worth the effort
register QRgb *i, *o, *b;
register int a;
register int j,k;
for (j=0; j<ch; j++)
{
b=reinterpret_cast<QRgb *>(&lower.scanLine(y+j) [ (x+cw) << 2 ]);
i=reinterpret_cast<QRgb *>(&upper.scanLine(cy+j)[ (cx+cw) << 2 ]);
o=reinterpret_cast<QRgb *>(&output.scanLine(j) [ cw << 2 ]);
k=cw-1;
--b; --i; --o;
do
{
while ( !(a=qAlpha(*i)) && k>0 )
{
i--;
// *o=0;
*o=*b;
--o; --b;
k--;
};
// *o=0xFF;
*o = qRgb(qRed(*b) + (((qRed(*i) - qRed(*b)) * a) >> 8),
qGreen(*b) + (((qGreen(*i) - qGreen(*b)) * a) >> 8),
qBlue(*b) + (((qBlue(*i) - qBlue(*b)) * a) >> 8));
--i; --o; --b;
} while (k--);
}
return true;
}
bool OImageEffect::blendOnLower(
int x, int y,
const QImage & upper,
const QImage & lower
)
{
int cx=0, cy=0, cw=upper.width(), ch=upper.height();
if ( upper.depth() != 32 || lower.depth() != 32 ) return false;
if ( x + cw > lower.width() ||
y + ch > lower.height() ||
x < 0 || y < 0 )
{
if ( x > lower.width() || y > lower.height() ) return true;
if ( upper.width()<=0 || upper.height() <= 0 ) return true;
if ( lower.width()<=0 || lower.height() <= 0 ) return true;
if (x<0) {cx=-x; cw+=x; x=0; };
if (cw + x > lower.width()) { cw=lower.width()-x; };
if (y<0) {cy=-y; ch+=y; y=0; };
if (ch + y > lower.height()) { ch=lower.height()-y; };
if ( cx >= upper.width() || cy >= upper.height() ) return true;
if ( cw <= 0 || ch <= 0 ) return true;
}
register uchar *i, *b;
register int a;
register int k;
for (int j=0; j<ch; j++)
{
b=&lower.scanLine(y+j) [ (x+cw) << 2 ];
i=&upper.scanLine(cy+j)[ (cx+cw) << 2 ];
k=cw-1;
--b; --i;
do
{
#ifndef WORDS_BIGENDIAN
while ( !(a=*i) && k>0 )
#else
while ( !(a=*(i-3)) && k>0 )
#endif
{
i-=4; b-=4; k--;
};
#ifndef WORDS_BIGENDIAN
--i; --b;
*b += ( ((*i - *b) * a) >> 8 );
--i; --b;
*b += ( ((*i - *b) * a) >> 8 );
--i; --b;
*b += ( ((*i - *b) * a) >> 8 );
--i; --b;
#else
*b += ( ((*i - *b) * a) >> 8 );
--i; --b;
*b += ( ((*i - *b) * a) >> 8 );
--i; --b;
*b += ( ((*i - *b) * a) >> 8 );
i -= 2; b -= 2;
#endif
} while (k--);
}
return true;
}
// For selected icons
QImage& OImageEffect::selectedImage( QImage &img, const QColor &col )
{
return blend( col, img, 0.5);
}
//
// ===================================================================
// Effects originally ported from ImageMagick for PixiePlus, plus a few
// new ones. (mosfet 12/29/01)
// ===================================================================
//
void OImageEffect::normalize(QImage &img)
{
int *histogram, threshold_intensity, intense;
int x, y, i;
unsigned int gray_value;
unsigned int *normalize_map;
unsigned int high, low;
// allocate histogram and normalize map
histogram = (int *)calloc(MaxRGB+1, sizeof(int));
normalize_map = (unsigned int *)malloc((MaxRGB+1)*sizeof(unsigned int));
if(!normalize_map || !histogram){
- qWarning("Unable to allocate normalize histogram and map");
+ owarn << "Unable to allocate normalize histogram and map" << oendl;
free(normalize_map);
free(histogram);
return;
}
// form histogram
if(img.depth() > 8){ // DirectClass
unsigned int *data;
for(y=0; y < img.height(); ++y){
data = (unsigned int *)img.scanLine(y);
for(x=0; x < img.width(); ++x){
gray_value = intensityValue(data[x]);
histogram[gray_value]++;
}
}
}
else{ // PsudeoClass
unsigned char *data;
unsigned int *cTable = img.colorTable();
for(y=0; y < img.height(); ++y){
data = (unsigned char *)img.scanLine(y);
for(x=0; x < img.width(); ++x){
gray_value = intensityValue(*(cTable+data[x]));
histogram[gray_value]++;
}
}
}
// find histogram boundaries by locating the 1 percent levels
threshold_intensity = (img.width()*img.height())/100;
intense = 0;
for(low=0; low < MaxRGB; ++low){
intense+=histogram[low];
if(intense > threshold_intensity)
break;
}
intense=0;
for(high=MaxRGB; high != 0; --high){
intense+=histogram[high];
if(intense > threshold_intensity)
break;
}
if (low == high){
// Unreasonable contrast; use zero threshold to determine boundaries.
threshold_intensity=0;
intense=0;
for(low=0; low < MaxRGB; ++low){
intense+=histogram[low];
if(intense > threshold_intensity)
break;
}
intense=0;
for(high=MaxRGB; high != 0; --high)
{
intense+=histogram[high];
if(intense > threshold_intensity)
break;
}
if(low == high)
return; // zero span bound
}
// Stretch the histogram to create the normalized image mapping.
for(i=0; i <= MaxRGB; i++){
if (i < (int) low)
normalize_map[i]=0;
else{
if(i > (int) high)
normalize_map[i]=MaxRGB;
else
normalize_map[i]=(MaxRGB-1)*(i-low)/(high-low);
}
}
// Normalize
if(img.depth() > 8){ // DirectClass
unsigned int *data;
for(y=0; y < img.height(); ++y){
data = (unsigned int *)img.scanLine(y);
for(x=0; x < img.width(); ++x){
data[x] = qRgba(normalize_map[qRed(data[x])],
normalize_map[qGreen(data[x])],
normalize_map[qBlue(data[x])],
qAlpha(data[x]));
}
}
}
else{ // PsudeoClass
int colors = img.numColors();
unsigned int *cTable = img.colorTable();
for(i=0; i < colors; ++i){
cTable[i] = qRgba(normalize_map[qRed(cTable[i])],
normalize_map[qGreen(cTable[i])],
normalize_map[qBlue(cTable[i])],
qAlpha(cTable[i]));
}
}
free(histogram);
free(normalize_map);
}
void OImageEffect::equalize(QImage &img)
{
int *histogram, *map, *equalize_map;
int x, y, i, j;
unsigned int high, low;
// allocate histogram and maps
histogram = (int *)calloc(MaxRGB+1, sizeof(int));
map = (int *)malloc((MaxRGB+1)*sizeof(unsigned int));
equalize_map = (int *)malloc((MaxRGB+1)*sizeof(unsigned int));
if(!histogram || !map || !equalize_map){
- qWarning("Unable to allocate equalize histogram and maps");
+ owarn << "Unable to allocate equalize histogram and maps" << oendl;
free(histogram);
free(map);
free(equalize_map);
return;
}
// form histogram
if(img.depth() > 8){ // DirectClass
unsigned int *data;
for(y=0; y < img.height(); ++y){
data = (unsigned int *)img.scanLine(y);
for(x=0; x < img.width(); ++x){
histogram[intensityValue(data[x])]++;
}
}
}
else{ // PsudeoClass
unsigned char *data;
unsigned int *cTable = img.colorTable();
for(y=0; y < img.height(); ++y){
data = (unsigned char *)img.scanLine(y);
for(x=0; x < img.width(); ++x){
histogram[intensityValue(*(cTable+data[x]))]++;
}
}
}
// integrate the histogram to get the equalization map.
j=0;
for(i=0; i <= MaxRGB; i++){
j+=histogram[i];
map[i]=j;
}
free(histogram);
if(map[MaxRGB] == 0){
free(equalize_map);
free(map);
return;
}
// equalize
low=map[0];
high=map[MaxRGB];
for(i=0; i <= MaxRGB; i++)
equalize_map[i]=(unsigned int)
((((double) (map[i]-low))*MaxRGB)/QMAX(high-low,1));
free(map);
// stretch the histogram
if(img.depth() > 8){ // DirectClass
unsigned int *data;
for(y=0; y < img.height(); ++y){
data = (unsigned int *)img.scanLine(y);
for(x=0; x < img.width(); ++x){
data[x] = qRgba(equalize_map[qRed(data[x])],
equalize_map[qGreen(data[x])],
equalize_map[qBlue(data[x])],
qAlpha(data[x]));
}
}
}
else{ // PsudeoClass
int colors = img.numColors();
unsigned int *cTable = img.colorTable();
for(i=0; i < colors; ++i){
cTable[i] = qRgba(equalize_map[qRed(cTable[i])],
equalize_map[qGreen(cTable[i])],
equalize_map[qBlue(cTable[i])],
qAlpha(cTable[i]));
}
}
free(equalize_map);
}
QImage OImageEffect::sample(QImage &src, int w, int h)
{
if(w == src.width() && h == src.height())
return(src);
double *x_offset, *y_offset;
int j, k, y;
register int x;
QImage dest(w, h, src.depth());
x_offset = (double *)malloc(w*sizeof(double));
y_offset = (double *)malloc(h*sizeof(double));
if(!x_offset || !y_offset){
- qWarning("Unable to allocate pixels buffer");
+ owarn << "Unable to allocate pixels buffer" << oendl;
free(x_offset);
free(y_offset);
return(src);
}
// init pixel offsets
for(x=0; x < w; ++x)
x_offset[x] = x*src.width()/((double)w);
for(y=0; y < h; ++y)
y_offset[y] = y*src.height()/((double)h);
// sample each row
if(src.depth() > 8){ // DirectClass source image
unsigned int *srcData, *destData;
unsigned int *pixels;
pixels = (unsigned int *)malloc(src.width()*sizeof(unsigned int));
if(!pixels){
- qWarning("Unable to allocate pixels buffer");
+ owarn << "Unable to allocate pixels buffer" << oendl;
free(pixels);
free(x_offset);
free(y_offset);
return(src);
}
j = (-1);
for(y=0; y < h; ++y){
destData = (unsigned int *)dest.scanLine(y);
if(j != y_offset[y]){
// read a scan line
j = (int)(y_offset[y]);
srcData = (unsigned int *)src.scanLine(j);
(void)memcpy(pixels, srcData, src.width()*sizeof(unsigned int));
}
// sample each column
for(x=0; x < w; ++x){
k = (int)(x_offset[x]);
destData[x] = pixels[k];
}
}
free(pixels);
}
else{ // PsudeoClass source image
unsigned char *srcData, *destData;
unsigned char *pixels;
pixels = (unsigned char *)malloc(src.width()*sizeof(unsigned char));
if(!pixels){
- qWarning("Unable to allocate pixels buffer");
+ owarn << "Unable to allocate pixels buffer" << oendl;
free(pixels);
free(x_offset);
free(y_offset);
return(src);
}
// copy colortable
dest.setNumColors(src.numColors());
(void)memcpy(dest.colorTable(), src.colorTable(),
src.numColors()*sizeof(unsigned int));
// sample image
j = (-1);
for(y=0; y < h; ++y){
destData = (unsigned char *)dest.scanLine(y);
if(j != y_offset[y]){
// read a scan line
j = (int)(y_offset[y]);
srcData = (unsigned char *)src.scanLine(j);
(void)memcpy(pixels, srcData, src.width()*sizeof(unsigned char));
}
// sample each column
for(x=0; x < w; ++x){
k = (int)(x_offset[x]);
destData[x] = pixels[k];
}
}
free(pixels);
}
free(x_offset);
free(y_offset);
return(dest);
}
void OImageEffect::threshold(QImage &img, unsigned int threshold)
{
int i, count;
unsigned int *data;
if(img.depth() > 8){ // DirectClass
count = img.width()*img.height();
data = (unsigned int *)img.bits();
}
else{ // PsudeoClass
count = img.numColors();
data = (unsigned int *)img.colorTable();
}
for(i=0; i < count; ++i)
data[i] = intensityValue(data[i]) < threshold ? Qt::black.rgb() : Qt::white.rgb();
}
QImage OImageEffect::charcoal(QImage &src, double factor)
{
QImage dest(src);
dest.detach();
toGray(dest);
dest = edge(dest, factor);
dest = blur(dest, factor);
normalize(dest);
dest.invertPixels(false);
return(dest);
}
void OImageEffect::hull(const int x_offset, const int y_offset,
const int polarity, const int columns,
const int rows,
unsigned int *f, unsigned int *g)
{
int x, y;
unsigned int *p, *q, *r, *s;
unsigned int v;
if(f == NULL || g == NULL)
return;
p=f+(columns+2);
q=g+(columns+2);
r=p+(y_offset*(columns+2)+x_offset);
for (y=0; y < rows; y++){
p++;
q++;
r++;
if(polarity > 0)
for (x=0; x < columns; x++){
v=(*p);
if (*r > v)
v++;
*q=v;
p++;
q++;
r++;
}
else
for(x=0; x < columns; x++){
v=(*p);
if (v > (unsigned int) (*r+1))
v--;
*q=v;
p++;
q++;
r++;
}
p++;
q++;
r++;
}
p=f+(columns+2);
q=g+(columns+2);
r=q+(y_offset*(columns+2)+x_offset);
s=q-(y_offset*(columns+2)+x_offset);
for(y=0; y < rows; y++){
p++;
q++;
r++;
s++;
if(polarity > 0)
for(x=0; x < (int) columns; x++){
v=(*q);
if (((unsigned int) (*s+1) > v) && (*r > v))
v++;
*p=v;
p++;
q++;
r++;
s++;
}
else
for (x=0; x < columns; x++){
v=(*q);
if (((unsigned int) (*s+1) < v) && (*r < v))
v--;
*p=v;
p++;
q++;
r++;
s++;
}
p++;
q++;
r++;
s++;
}
}
QImage OImageEffect::despeckle(QImage &src)
{
int i, j, x, y;
unsigned int *blue_channel, *red_channel, *green_channel, *buffer,
*alpha_channel;
int packets;
static const int
X[4]= {0, 1, 1,-1},
Y[4]= {1, 0, 1, 1};
unsigned int *destData;
QImage dest(src.width(), src.height(), 32);
packets = (src.width()+2)*(src.height()+2);
red_channel = (unsigned int *)calloc(packets, sizeof(unsigned int));
green_channel = (unsigned int *)calloc(packets, sizeof(unsigned int));
blue_channel = (unsigned int *)calloc(packets, sizeof(unsigned int));
alpha_channel = (unsigned int *)calloc(packets, sizeof(unsigned int));
buffer = (unsigned int *)calloc(packets, sizeof(unsigned int));
if(!red_channel || ! green_channel || ! blue_channel || ! alpha_channel ||
!buffer){
free(red_channel);
free(green_channel);
free(blue_channel);
free(alpha_channel);
free(buffer);
return(src);
}
// copy image pixels to color component buffers
j = src.width()+2;
if(src.depth() > 8){ // DirectClass source image
unsigned int *srcData;
for(y=0; y < src.height(); ++y){
srcData = (unsigned int *)src.scanLine(y);
++j;
for(x=0; x < src.width(); ++x){
red_channel[j] = qRed(srcData[x]);
green_channel[j] = qGreen(srcData[x]);
blue_channel[j] = qBlue(srcData[x]);
alpha_channel[j] = qAlpha(srcData[x]);
++j;
}
++j;
}
}
else{ // PsudeoClass source image
unsigned char *srcData;
unsigned int *cTable = src.colorTable();
unsigned int pixel;
for(y=0; y < src.height(); ++y){
srcData = (unsigned char *)src.scanLine(y);
++j;
for(x=0; x < src.width(); ++x){
pixel = *(cTable+srcData[x]);
red_channel[j] = qRed(pixel);
green_channel[j] = qGreen(pixel);
blue_channel[j] = qBlue(pixel);
alpha_channel[j] = qAlpha(pixel);
++j;
}
++j;
}
}
// reduce speckle in red channel
for(i=0; i < 4; i++){
hull(X[i],Y[i],1,src.width(),src.height(),red_channel,buffer);
hull(-X[i],-Y[i],1,src.width(),src.height(),red_channel,buffer);
hull(-X[i],-Y[i],-1,src.width(),src.height(),red_channel,buffer);
hull(X[i],Y[i],-1,src.width(),src.height(),red_channel,buffer);
}
// reduce speckle in green channel
for (i=0; i < packets; i++)
buffer[i]=0;
for (i=0; i < 4; i++){
hull(X[i],Y[i],1,src.width(),src.height(),green_channel,buffer);
hull(-X[i],-Y[i],1,src.width(),src.height(),green_channel,buffer);
hull(-X[i],-Y[i],-1,src.width(),src.height(),green_channel,buffer);
hull(X[i],Y[i],-1,src.width(),src.height(),green_channel,buffer);
}
// reduce speckle in blue channel
for (i=0; i < packets; i++)
buffer[i]=0;
for (i=0; i < 4; i++){
hull(X[i],Y[i],1,src.width(),src.height(),blue_channel,buffer);
hull(-X[i],-Y[i],1,src.width(),src.height(),blue_channel,buffer);
hull(-X[i],-Y[i],-1,src.width(),src.height(),blue_channel,buffer);
hull(X[i],Y[i],-1,src.width(),src.height(),blue_channel,buffer);
}
// copy color component buffers to despeckled image
j = dest.width()+2;
for(y=0; y < dest.height(); ++y)
{
destData = (unsigned int *)dest.scanLine(y);
++j;
for (x=0; x < dest.width(); ++x)
{
destData[x] = qRgba(red_channel[j], green_channel[j],
blue_channel[j], alpha_channel[j]);
++j;
}
++j;
}
free(buffer);
free(red_channel);
free(green_channel);
free(blue_channel);
free(alpha_channel);
return(dest);
}
unsigned int OImageEffect::generateNoise(unsigned int pixel,
NoiseType noise_type)
{
#define NoiseEpsilon 1.0e-5
#define NoiseMask 0x7fff
#define SigmaUniform 4.0
#define SigmaGaussian 4.0
#define SigmaImpulse 0.10
#define SigmaLaplacian 10.0
#define SigmaMultiplicativeGaussian 0.5
#define SigmaPoisson 0.05
#define TauGaussian 20.0
double alpha, beta, sigma, value;
alpha=(double) (rand() & NoiseMask)/NoiseMask;
if (alpha == 0.0)
alpha=1.0;
switch(noise_type){
case UniformNoise:
default:
{
value=(double) pixel+SigmaUniform*(alpha-0.5);
break;
}
case GaussianNoise:
{
double tau;
beta=(double) (rand() & NoiseMask)/NoiseMask;
sigma=sqrt(-2.0*log(alpha))*cos(2.0*M_PI*beta);
tau=sqrt(-2.0*log(alpha))*sin(2.0*M_PI*beta);
value=(double) pixel+
(sqrt((double) pixel)*SigmaGaussian*sigma)+(TauGaussian*tau);
break;
}
case MultiplicativeGaussianNoise:
{
if (alpha <= NoiseEpsilon)
sigma=MaxRGB;
else
sigma=sqrt(-2.0*log(alpha));
beta=(rand() & NoiseMask)/NoiseMask;
value=(double) pixel+
pixel*SigmaMultiplicativeGaussian*sigma*cos(2.0*M_PI*beta);
break;
}
case ImpulseNoise:
{
if (alpha < (SigmaImpulse/2.0))
value=0;
else
if (alpha >= (1.0-(SigmaImpulse/2.0)))
value=MaxRGB;
else
value=pixel;
break;
}
case LaplacianNoise:
{
if (alpha <= 0.5)
{
if (alpha <= NoiseEpsilon)
value=(double) pixel-MaxRGB;
else
value=(double) pixel+SigmaLaplacian*log(2.0*alpha);
break;
}
beta=1.0-alpha;
if (beta <= (0.5*NoiseEpsilon))
value=(double) pixel+MaxRGB;
else
value=(double) pixel-SigmaLaplacian*log(2.0*beta);
break;
}
case PoissonNoise:
{
register int
i;
for (i=0; alpha > exp(-SigmaPoisson*pixel); i++)
{
beta=(double) (rand() & NoiseMask)/NoiseMask;
alpha=alpha*beta;
}
value=i/SigmaPoisson;
break;
}
}
if(value < 0.0)
return(0);
if(value > MaxRGB)
return(MaxRGB);
return((unsigned int) (value+0.5));
}
QImage OImageEffect::addNoise(QImage &src, NoiseType noise_type)
{
int x, y;
QImage dest(src.width(), src.height(), 32);
unsigned int *destData;
if(src.depth() > 8){ // DirectClass source image
unsigned int *srcData;
for(y=0; y < src.height(); ++y){
srcData = (unsigned int *)src.scanLine(y);
destData = (unsigned int *)dest.scanLine(y);
for(x=0; x < src.width(); ++x){
destData[x] = qRgba(generateNoise(qRed(srcData[x]), noise_type),
generateNoise(qGreen(srcData[x]), noise_type),
generateNoise(qBlue(srcData[x]), noise_type),
qAlpha(srcData[x]));
}
}
}
else{ // PsudeoClass source image
unsigned char *srcData;
unsigned int *cTable = src.colorTable();
unsigned int pixel;
for(y=0; y < src.height(); ++y){
srcData = (unsigned char *)src.scanLine(y);
destData = (unsigned int *)dest.scanLine(y);
for(x=0; x < src.width(); ++x){
pixel = *(cTable+srcData[x]);
destData[x] = qRgba(generateNoise(qRed(pixel), noise_type),
generateNoise(qGreen(pixel), noise_type),
generateNoise(qBlue(pixel), noise_type),
qAlpha(pixel));
}
}
}
return(dest);
}
unsigned int OImageEffect::interpolateColor(QImage *image, double x_offset,
double y_offset,
unsigned int background)
{
double alpha, beta;
unsigned int p, q, r, s;
int x, y;
x = (int)x_offset;
y = (int)y_offset;
if((x < -1) || (x >= image->width()) || (y < -1) || (y >= image->height()))
return(background);
if(image->depth() > 8){
if((x >= 0) && (y >= 0) && (x < (image->width()-1)) && (y < (image->height()-1))) {
unsigned int *t = (unsigned int *)image->scanLine(y);
p = t[x];
q = t[x+1];
r = t[x+image->width()];
s = t[x+image->width()+1];
}
else{
unsigned int *t = (unsigned int *)image->scanLine(y);
p = background;
if((x >= 0) && (y >= 0)){
p = t[x];
}
q = background;
if(((x+1) < image->width()) && (y >= 0)){
q = t[x+1];
}
r = background;
if((x >= 0) && ((y+1) < image->height())){
t = (unsigned int *)image->scanLine(y+1);
r = t[x+image->width()];
}
s = background;
if(((x+1) < image->width()) && ((y+1) < image->height())){
t = (unsigned int *)image->scanLine(y+1);
s = t[x+image->width()+1];
}
}
}
else{
unsigned int *colorTable = (unsigned int *)image->colorTable();
if((x >= 0) && (y >= 0) && (x < (image->width()-1)) && (y < (image->height()-1))) {
unsigned char *t;
t = (unsigned char *)image->scanLine(y);
p = *(colorTable+t[x]);
q = *(colorTable+t[x+1]);
t = (unsigned char *)image->scanLine(y+1);
r = *(colorTable+t[x]);
s = *(colorTable+t[x+1]);
}
else{
unsigned char *t;
p = background;
if((x >= 0) && (y >= 0)){
t = (unsigned char *)image->scanLine(y);
p = *(colorTable+t[x]);
}
q = background;
if(((x+1) < image->width()) && (y >= 0)){
t = (unsigned char *)image->scanLine(y);
q = *(colorTable+t[x+1]);
}
r = background;
if((x >= 0) && ((y+1) < image->height())){
t = (unsigned char *)image->scanLine(y+1);
r = *(colorTable+t[x]);
}
s = background;
if(((x+1) < image->width()) && ((y+1) < image->height())){
t = (unsigned char *)image->scanLine(y+1);
s = *(colorTable+t[x+1]);
}
}
}
x_offset -= floor(x_offset);
y_offset -= floor(y_offset);
alpha = 1.0-x_offset;
beta = 1.0-y_offset;
return(qRgba((unsigned char)(beta*(alpha*qRed(p)+x_offset*qRed(q))+y_offset*(alpha*qRed(r)+x_offset*qRed(s))),
(unsigned char)(beta*(alpha*qGreen(p)+x_offset*qGreen(q))+y_offset*(alpha*qGreen(r)+x_offset*qGreen(s))),
(unsigned char)(beta*(alpha*qBlue(p)+x_offset*qBlue(q))+y_offset*(alpha*qBlue(r)+x_offset*qBlue(s))),
(unsigned char)(beta*(alpha*qAlpha(p)+x_offset*qAlpha(q))+y_offset*(alpha*qAlpha(r)+x_offset*qAlpha(s)))));
}
QImage OImageEffect::implode(QImage &src, double factor,
unsigned int background)
{
double amount, distance, radius;
double x_center, x_distance, x_scale;
double y_center, y_distance, y_scale;
unsigned int *destData;
int x, y;
QImage dest(src.width(), src.height(), 32);
// compute scaling factor
x_scale = 1.0;
y_scale = 1.0;
x_center = (double)0.5*src.width();
y_center = (double)0.5*src.height();
radius=x_center;
if(src.width() > src.height())
y_scale = (double)src.width()/src.height();
else if(src.width() < src.height()){
x_scale = (double) src.height()/src.width();
radius = y_center;
}
amount=factor/10.0;
if(amount >= 0)
amount/=10.0;
if(src.depth() > 8){ // DirectClass source image
unsigned int *srcData;
for(y=0; y < src.height(); ++y){
srcData = (unsigned int *)src.scanLine(y);
destData = (unsigned int *)dest.scanLine(y);
y_distance=y_scale*(y-y_center);
for(x=0; x < src.width(); ++x){
destData[x] = srcData[x];
x_distance = x_scale*(x-x_center);
distance= x_distance*x_distance+y_distance*y_distance;
if(distance < (radius*radius)){
double factor;
// Implode the pixel.
factor=1.0;
if(distance > 0.0)
factor=
pow(sin(0.5000000000000001*M_PI*sqrt(distance)/radius),-amount);
destData[x] = interpolateColor(&src, factor*x_distance/x_scale+x_center,
factor*y_distance/y_scale+y_center,
background);
}
}
}
}
else{ // PsudeoClass source image
unsigned char *srcData;
unsigned char idx;
unsigned int *cTable = src.colorTable();
for(y=0; y < src.height(); ++y){
srcData = (unsigned char *)src.scanLine(y);
destData = (unsigned int *)dest.scanLine(y);
y_distance=y_scale*(y-y_center);
for(x=0; x < src.width(); ++x){
idx = srcData[x];
destData[x] = cTable[idx];
x_distance = x_scale*(x-x_center);
distance= x_distance*x_distance+y_distance*y_distance;
if(distance < (radius*radius)){
double factor;
// Implode the pixel.
factor=1.0;
if(distance > 0.0)
factor=
pow(sin(0.5000000000000001*M_PI*sqrt(distance)/radius),-amount);
destData[x] = interpolateColor(&src, factor*x_distance/x_scale+x_center,
factor*y_distance/y_scale+y_center,
background);
}
}
}
}
return(dest);
}
QImage OImageEffect::rotate(QImage &img, RotateDirection r)
{
QImage dest;
int x, y;
if(img.depth() > 8){
unsigned int *srcData, *destData;
switch(r){
case Rotate90:
dest.create(img.height(), img.width(), img.depth());
for(y=0; y < img.height(); ++y){
srcData = (unsigned int *)img.scanLine(y);
for(x=0; x < img.width(); ++x){
destData = (unsigned int *)dest.scanLine(x);
destData[img.height()-y-1] = srcData[x];
}
}
break;
case Rotate180:
dest.create(img.width(), img.height(), img.depth());
for(y=0; y < img.height(); ++y){
srcData = (unsigned int *)img.scanLine(y);
destData = (unsigned int *)dest.scanLine(img.height()-y-1);
for(x=0; x < img.width(); ++x)
destData[img.width()-x-1] = srcData[x];
}
break;
case Rotate270:
dest.create(img.height(), img.width(), img.depth());
for(y=0; y < img.height(); ++y){
srcData = (unsigned int *)img.scanLine(y);
for(x=0; x < img.width(); ++x){
destData = (unsigned int *)dest.scanLine(img.width()-x-1);
destData[y] = srcData[x];
}
}
break;
default:
dest = img;
break;
}
}
else{
unsigned char *srcData, *destData;
unsigned int *srcTable, *destTable;
switch(r){
case Rotate90:
dest.create(img.height(), img.width(), img.depth());
dest.setNumColors(img.numColors());
srcTable = (unsigned int *)img.colorTable();
destTable = (unsigned int *)dest.colorTable();
for(x=0; x < img.numColors(); ++x)
destTable[x] = srcTable[x];
for(y=0; y < img.height(); ++y){
srcData = (unsigned char *)img.scanLine(y);
for(x=0; x < img.width(); ++x){
destData = (unsigned char *)dest.scanLine(x);
destData[img.height()-y-1] = srcData[x];
}
}
break;
case Rotate180:
dest.create(img.width(), img.height(), img.depth());
dest.setNumColors(img.numColors());
srcTable = (unsigned int *)img.colorTable();
destTable = (unsigned int *)dest.colorTable();
for(x=0; x < img.numColors(); ++x)
destTable[x] = srcTable[x];
for(y=0; y < img.height(); ++y){
srcData = (unsigned char *)img.scanLine(y);
destData = (unsigned char *)dest.scanLine(img.height()-y-1);
for(x=0; x < img.width(); ++x)
destData[img.width()-x-1] = srcData[x];
}
break;
case Rotate270:
dest.create(img.height(), img.width(), img.depth());
dest.setNumColors(img.numColors());
srcTable = (unsigned int *)img.colorTable();
destTable = (unsigned int *)dest.colorTable();
for(x=0; x < img.numColors(); ++x)
destTable[x] = srcTable[x];
for(y=0; y < img.height(); ++y){
srcData = (unsigned char *)img.scanLine(y);
for(x=0; x < img.width(); ++x){
destData = (unsigned char *)dest.scanLine(img.width()-x-1);
destData[y] = srcData[x];
}
}
break;
default:
dest = img;
break;
}
}
return(dest);
}
void OImageEffect::solarize(QImage &img, double factor)
{
int i, count;
int threshold;
unsigned int *data;
threshold = (int)(factor*(MaxRGB+1)/100.0);
if(img.depth() < 32){
data = (unsigned int *)img.colorTable();
count = img.numColors();
}
else{
data = (unsigned int *)img.bits();
count = img.width()*img.height();
}
for(i=0; i < count; ++i){
data[i] = qRgba(qRed(data[i]) > threshold ? MaxRGB-qRed(data[i]) : qRed(data[i]),
qGreen(data[i]) > threshold ? MaxRGB-qGreen(data[i]) : qGreen(data[i]),
qBlue(data[i]) > threshold ? MaxRGB-qBlue(data[i]) : qBlue(data[i]),
qAlpha(data[i]));
}
}
QImage OImageEffect::spread(QImage &src, unsigned int amount)
{
int quantum, x, y;
int x_distance, y_distance;
if(src.width() < 3 || src.height() < 3)
return(src);
QImage dest(src);
dest.detach();
quantum=(amount+1) >> 1;
if(src.depth() > 8){ // DirectClass source image
unsigned int *p, *q;
for(y=0; y < src.height(); y++){
q = (unsigned int *)dest.scanLine(y);
for(x=0; x < src.width(); x++){
x_distance = x + ((rand() & (amount+1))-quantum);
y_distance = y + ((rand() & (amount+1))-quantum);
x_distance = QMIN(x_distance, src.width()-1);
y_distance = QMIN(y_distance, src.height()-1);
if(x_distance < 0)
x_distance = 0;
if(y_distance < 0)
y_distance = 0;
p = (unsigned int *)src.scanLine(y_distance);
p += x_distance;
*q++=(*p);
}
}
}
else{ // PsudeoClass source image
// just do colortable values
unsigned char *p, *q;
for(y=0; y < src.height(); y++){
q = (unsigned char *)dest.scanLine(y);
for(x=0; x < src.width(); x++){
x_distance = x + ((rand() & (amount+1))-quantum);
y_distance = y + ((rand() & (amount+1))-quantum);
x_distance = QMIN(x_distance, src.width()-1);
y_distance = QMIN(y_distance, src.height()-1);
if(x_distance < 0)
x_distance = 0;
if(y_distance < 0)
y_distance = 0;
p = (unsigned char *)src.scanLine(y_distance);
p += x_distance;
*q++=(*p);
}
}
}
return(dest);
}
QImage OImageEffect::swirl(QImage &src, double degrees,
unsigned int background)
{
double cosine, distance, factor, radius, sine, x_center, x_distance,
x_scale, y_center, y_distance, y_scale;
int x, y;
unsigned int *q;
QImage dest(src.width(), src.height(), 32);
// compute scaling factor
x_center = src.width()/2.0;
y_center = src.height()/2.0;
radius = QMAX(x_center,y_center);
x_scale=1.0;
y_scale=1.0;
if(src.width() > src.height())
y_scale=(double)src.width()/src.height();
else if(src.width() < src.height())
x_scale=(double)src.height()/src.width();
degrees=DegreesToRadians(degrees);
// swirl each row
if(src.depth() > 8){ // DirectClass source image
unsigned int *p;
for(y=0; y < src.height(); y++){
p = (unsigned int *)src.scanLine(y);
q = (unsigned int *)dest.scanLine(y);
y_distance = y_scale*(y-y_center);
for(x=0; x < src.width(); x++){
// determine if the pixel is within an ellipse
*q=(*p);
x_distance = x_scale*(x-x_center);
distance = x_distance*x_distance+y_distance*y_distance;
if (distance < (radius*radius)){
// swirl
factor = 1.0-sqrt(distance)/radius;
sine = sin(degrees*factor*factor);
cosine = cos(degrees*factor*factor);
*q = interpolateColor(&src,
(cosine*x_distance-sine*y_distance)/x_scale+x_center,
(sine*x_distance+cosine*y_distance)/y_scale+y_center,
background);
}
p++;
q++;
}
}
}
else{ // PsudeoClass source image
unsigned char *p;
unsigned int *cTable = (unsigned int *)src.colorTable();
for(y=0; y < src.height(); y++){
p = (unsigned char *)src.scanLine(y);
q = (unsigned int *)dest.scanLine(y);
y_distance = y_scale*(y-y_center);
for(x=0; x < src.width(); x++){
// determine if the pixel is within an ellipse
*q = *(cTable+(*p));
x_distance = x_scale*(x-x_center);
distance = x_distance*x_distance+y_distance*y_distance;
if (distance < (radius*radius)){
// swirl
factor = 1.0-sqrt(distance)/radius;
sine = sin(degrees*factor*factor);
cosine = cos(degrees*factor*factor);
*q = interpolateColor(&src,
(cosine*x_distance-sine*y_distance)/x_scale+x_center,
(sine*x_distance+cosine*y_distance)/y_scale+y_center,
background);
}
p++;
q++;
}
}
}
return(dest);
}
QImage OImageEffect::wave(QImage &src, double amplitude, double wavelength,
unsigned int background)
{
double *sine_map;
int x, y;
unsigned int *q;
QImage dest(src.width(), src.height() + (int)(2*fabs(amplitude)), 32);
// allocate sine map
sine_map = (double *)malloc(dest.width()*sizeof(double));
if(!sine_map)
return(src);
for(x=0; x < dest.width(); ++x)
sine_map[x]=fabs(amplitude)+amplitude*sin((2*M_PI*x)/wavelength);
// wave image
for(y=0; y < dest.height(); ++y){
q = (unsigned int *)dest.scanLine(y);
for (x=0; x < dest.width(); x++){
*q=interpolateColor(&src, x, (int)(y-sine_map[x]), background);
++q;
}
}
free(sine_map);
return(dest);
}
QImage OImageEffect::oilPaint(QImage &src, int radius)
{
// TODO 8bpp src!
if(src.depth() < 32){
- qWarning("Oil Paint source image < 32bpp. Convert before using!");
+ owarn << "Oil Paint source image < 32bpp. Convert before using!" << oendl;
return(src);
}
int j, k, i, x, y;
unsigned int *histogram;
unsigned int *s;
unsigned int count;
unsigned int *srcData, *destData;
QImage dest(src);
dest.detach();
histogram = (unsigned int *) malloc((MaxRGB+1)*sizeof(unsigned int));
if(!histogram)
return(src);
// paint each row
k=0;
for(y = radius; y < src.height(); ++y){
srcData = (unsigned int *)src.scanLine(y-radius);
destData = (unsigned int *)dest.scanLine(y);
srcData += radius*src.width()+radius;
destData += radius;
for(x=radius; x < src.width()-radius; ++x){
// determine most frequent color
count = 0;
for(i=0; i < MaxRGB+1; ++i)
histogram[i] = 0;
for(i=0; i < radius; ++i){
s = srcData-(radius-1)*src.width()-i-1;
for(j =0; j < (2*i+1); ++j){
k = intensityValue(*s);
histogram[k]++;
if(histogram[k] > count){
*destData = *s;
count = histogram[k];
}
++s;
}
s = srcData+(radius-i)*src.width()-i-1;
for(j =0; j < (2*i+1); ++j){
k = intensityValue(*s);
histogram[k]++;
if(histogram[k] > count){
*destData = *s;
count = histogram[k];
}
++s;
}
}
s = srcData-radius;
for(j =0; j < (2*i+1); ++j){
k = intensityValue(*s);
histogram[k]++;
if(histogram[k] > count){
*destData = *s;
count = histogram[k];
}
++s;
}
++srcData;
++destData;
}
}
free(histogram);
return(dest);
}
//
// The following methods work by computing a value from neighboring pixels
// (mosfet 12/28/01)
//
QImage OImageEffect::edge(QImage &src, double factor)
{
#define Edge(weight) \
total_red+=(weight)*qRed(*s); \
total_green+=(weight)*qGreen(*s); \
total_blue+=(weight)*qBlue(*s); \
total_opacity+=(weight)*qAlpha(*s); \
s++;
#define Edge256(weight) \
total_red+=(weight)*qRed(*(cTable+(*s))); \
total_green+=(weight)*qGreen(*(cTable+(*s))); \
total_blue+=(weight)*qBlue(*(cTable+(*s))); \
total_opacity+=(weight)*qAlpha(*(cTable+(*s))); \
s++;
if(src.width() < 3 || src.height() < 3)
return(src);
double total_blue, total_green, total_opacity, total_red, weight;
int x, y;
unsigned int *q;
QImage dest(src.width(), src.height(), 32);
weight=factor/8.0;
if(src.depth() > 8){ // DirectClass source image
unsigned int *p, *s;
for(y=0; y < src.height(); ++y){
p = (unsigned int *)src.scanLine(QMIN(QMAX(y-1,0),src.height()-3));
q = (unsigned int *)dest.scanLine(y);
// edge detect this row of pixels.
*q++=(*(p+src.width()));
for(x=1; x < src.width()-1; ++x){
// compute weighted average of target pixel color components.
total_red=0.0;
total_green=0.0;
total_blue=0.0;
total_opacity=0.0;
s=p;
Edge(-weight/8); Edge(-weight/8) Edge(-weight/8);
s=p+src.width();
Edge(-weight/8); Edge(weight); Edge(-weight/8);
s=p+2*src.width();
Edge(-weight/8); Edge(-weight/8); Edge(-weight/8);
*q = qRgba((unsigned char)((total_red < 0) ? 0 : (total_red > MaxRGB) ? MaxRGB : total_red),
(unsigned char)((total_green < 0) ? 0 : (total_green > MaxRGB) ? MaxRGB : total_green),
(unsigned char)((total_blue < 0) ? 0 : (total_blue > MaxRGB) ? MaxRGB : total_blue),
(unsigned char)((total_opacity < 0) ? 0 : (total_opacity > MaxRGB) ? MaxRGB : total_opacity));
p++;
q++;
}
p++;
*q++=(*p);
}
}
else{ // PsudeoClass source image
unsigned char *p, *p2, *p3, *s;
unsigned int *cTable = src.colorTable();
int scanLineIdx;
for(y=0; y < src.height(); ++y){
scanLineIdx = QMIN(QMAX(y-1,0),src.height()-3);
p = (unsigned char *)src.scanLine(scanLineIdx);
p2 = (unsigned char *)src.scanLine(scanLineIdx+1);
p3 = (unsigned char *)src.scanLine(scanLineIdx+2);
q = (unsigned int *)dest.scanLine(y);
// edge detect this row of pixels.
*q++=(*(cTable+(*p2)));
for(x=1; x < src.width()-1; ++x){
// compute weighted average of target pixel color components.
total_red=0.0;
total_green=0.0;
total_blue=0.0;
total_opacity=0.0;
s=p;
Edge256(-weight/8); Edge256(-weight/8) Edge256(-weight/8);
s=p2;
Edge256(-weight/8); Edge256(weight); Edge256(-weight/8);
s=p3;
Edge256(-weight/8); Edge256(-weight/8); Edge256(-weight/8);
*q = qRgba((unsigned char)((total_red < 0) ? 0 : (total_red > MaxRGB) ? MaxRGB : total_red),
(unsigned char)((total_green < 0) ? 0 : (total_green > MaxRGB) ? MaxRGB : total_green),
(unsigned char)((total_blue < 0) ? 0 : (total_blue > MaxRGB) ? MaxRGB : total_blue),
(unsigned char)((total_opacity < 0) ? 0 : (total_opacity > MaxRGB) ? MaxRGB : total_opacity));
p++;
p2++;
p3++;
q++;
}
p++;
*q++=(*(cTable+(*p)));
}
}
return(dest);
}
QImage OImageEffect::sharpen(QImage &src, double factor)
{
#define Sharpen(weight) \
total_red+=(weight)*qRed(*s); \
total_green+=(weight)*qGreen(*s); \
total_blue+=(weight)*qBlue(*s); \
total_opacity+=(weight)*qAlpha(*s); \
s++;
#define Sharpen256(weight) \
total_red+=(weight)*qRed(*(cTable+(*s))); \
total_green+=(weight)*qGreen(*(cTable+(*s))); \
total_blue+=(weight)*qBlue(*(cTable+(*s))); \
total_opacity+=(weight)*qAlpha(*(cTable+(*s))); \
s++;
if(src.width() < 3 || src.height() < 3)
return(src);
double total_blue, total_green, total_opacity, total_red;
double quantum, weight;
unsigned char r, g, b, a;
int x, y;
unsigned int *q;
QImage dest(src.width(), src.height(), 32);
weight = ((100.0-factor)/2.0+13.0);
quantum = QMAX(weight-12.0, 1.0);
if(src.depth() > 8){ // DirectClass source image
unsigned int *p, *s;
for(y=0; y < src.height(); ++y){
p = (unsigned int *)src.scanLine(QMIN(QMAX(y-1,0),src.height()-3));
q = (unsigned int *)dest.scanLine(y);
// sharpen this row of pixels.
*q++=(*(p+src.width()));
for(x=1; x < src.width()-1; ++x){
// compute weighted average of target pixel color components.
total_red=0.0;
total_green=0.0;
total_blue=0.0;
total_opacity=0.0;
s=p;
Sharpen(-1); Sharpen(-2); Sharpen(-1);
s=p+src.width();
Sharpen(-2); Sharpen(weight); Sharpen(-2);
s=p+2*src.width();
Sharpen(-1); Sharpen(-2); Sharpen(-1);
if(total_red < 0)
r=0;
else if(total_red > (int)(MaxRGB*quantum))
r = (unsigned char)MaxRGB;
else
r = (unsigned char)((total_red+(quantum/2.0))/quantum);
if(total_green < 0)
g = 0;
else if(total_green > (int)(MaxRGB*quantum))
g = (unsigned char)MaxRGB;
else
g = (unsigned char)((total_green+(quantum/2.0))/quantum);
if(total_blue < 0)
b = 0;
else if(total_blue > (int)(MaxRGB*quantum))
b = (unsigned char)MaxRGB;
else
b = (unsigned char)((total_blue+(quantum/2.0))/quantum);
if(total_opacity < 0)
a = 0;
else if(total_opacity > (int)(MaxRGB*quantum))
a = (unsigned char)MaxRGB;
else
a= (unsigned char)((total_opacity+(quantum/2.0))/quantum);
*q = qRgba(r, g, b, a);
p++;
q++;
}
p++;
*q++=(*p);
}
}
else{ // PsudeoClass source image
unsigned char *p, *p2, *p3, *s;
unsigned int *cTable = src.colorTable();
int scanLineIdx;
for(y=0; y < src.height(); ++y){
scanLineIdx = QMIN(QMAX(y-1,0),src.height()-3);
p = (unsigned char *)src.scanLine(scanLineIdx);
p2 = (unsigned char *)src.scanLine(scanLineIdx+1);
p3 = (unsigned char *)src.scanLine(scanLineIdx+2);
q = (unsigned int *)dest.scanLine(y);
// sharpen this row of pixels.
*q++=(*(cTable+(*p2)));
for(x=1; x < src.width()-1; ++x){
// compute weighted average of target pixel color components.
total_red=0.0;
total_green=0.0;
total_blue=0.0;
total_opacity=0.0;
s=p;
Sharpen256(-1); Sharpen256(-2); Sharpen256(-1);
s=p2;
Sharpen256(-2); Sharpen256(weight); Sharpen256(-2);
s=p3;
Sharpen256(-1); Sharpen256(-2); Sharpen256(-1);
if(total_red < 0)
r=0;
else if(total_red > (int)(MaxRGB*quantum))
r = (unsigned char)MaxRGB;
else
r = (unsigned char)((total_red+(quantum/2.0))/quantum);
if(total_green < 0)
g = 0;
else if(total_green > (int)(MaxRGB*quantum))
g = (unsigned char)MaxRGB;
else
g = (unsigned char)((total_green+(quantum/2.0))/quantum);
if(total_blue < 0)
b = 0;
else if(total_blue > (int)(MaxRGB*quantum))
b = (unsigned char)MaxRGB;
else
b = (unsigned char)((total_blue+(quantum/2.0))/quantum);
if(total_opacity < 0)
a = 0;
else if(total_opacity > (int)(MaxRGB*quantum))
a = (unsigned char)MaxRGB;
else
a = (unsigned char)((total_opacity+(quantum/2.0))/quantum);
*q = qRgba(r, g, b, a);
p++;
p2++;
p3++;
q++;
}
p++;
*q++=(*(cTable+(*p)));
}
}
return(dest);
}
QImage OImageEffect::emboss(QImage &src)
{
#define Emboss(weight) \
total_red+=(weight)*qRed(*s); \
total_green+=(weight)*qGreen(*s); \
total_blue+=(weight)*qBlue(*s); \
s++;
#define Emboss256(weight) \
total_red+=(weight)*qRed(*(cTable+(*s))); \
total_green+=(weight)*qGreen(*(cTable+(*s))); \
total_blue+=(weight)*qBlue(*(cTable+(*s))); \
s++;
if(src.width() < 3 || src.height() < 3)
return(src);
double total_blue, total_green, total_red;
int x, y;
unsigned int *q;
QImage dest(src.width(), src.height(), 32);
if(src.depth() > 8){ // DirectClass source image
unsigned int *p, *s;
for(y=0; y < src.height(); ++y){
p = (unsigned int *)src.scanLine(QMIN(QMAX(y-1,0),src.height()-3));
q = (unsigned int *)dest.scanLine(y);
// emboss this row of pixels.
*q++=(*(p+src.width()));
for(x=1; x < src.width()-1; ++x){
// compute weighted average of target pixel color components.
total_red=0.0;
total_green=0.0;
total_blue=0.0;
s=p;
Emboss(-1); Emboss(-2); Emboss( 0);
s=p+src.width();
Emboss(-2); Emboss( 0); Emboss( 2);
s=p+2*src.width();
Emboss( 0); Emboss( 2); Emboss( 1);
total_red += (MaxRGB+1)/2;
total_green += (MaxRGB+1)/2;
total_blue += (MaxRGB+1)/2;
*q = qRgba((unsigned char)((total_red < 0) ? 0 : (total_red > MaxRGB) ? MaxRGB : total_red),
(unsigned char)((total_green < 0) ? 0 : (total_green > MaxRGB) ? MaxRGB : total_green),
(unsigned char)((total_blue < 0) ? 0 : (total_blue > MaxRGB) ? MaxRGB : total_blue),
255);
p++;
q++;
}
p++;
*q++=(*p);
}
}
else{ // PsudeoClass source image
unsigned char *p, *p2, *p3, *s;
unsigned int *cTable = src.colorTable();
int scanLineIdx;
for(y=0; y < src.height(); ++y){
scanLineIdx = QMIN(QMAX(y-1,0),src.height()-3);
p = (unsigned char *)src.scanLine(scanLineIdx);
p2 = (unsigned char *)src.scanLine(scanLineIdx+1);
p3 = (unsigned char *)src.scanLine(scanLineIdx+2);
q = (unsigned int *)dest.scanLine(y);
// emboss this row of pixels.
*q++=(*(cTable+(*p2)));
for(x=1; x < src.width()-1; ++x){
// compute weighted average of target pixel color components.
total_red=0.0;
total_green=0.0;
total_blue=0.0;
s=p;
Emboss256(-1); Emboss256(-2); Emboss256(0);
s=p2;
Emboss256(-2); Emboss256(0); Emboss256(2);
s=p3;
Emboss256(0); Emboss256(2); Emboss256(1);
total_red += (MaxRGB+1)/2;
total_green += (MaxRGB+1)/2;
total_blue += (MaxRGB+1)/2;
*q = qRgba((unsigned char)((total_red < 0) ? 0 : (total_red > MaxRGB) ? MaxRGB : total_red),
(unsigned char)((total_green < 0) ? 0 : (total_green > MaxRGB) ? MaxRGB : total_green),
(unsigned char)((total_blue < 0) ? 0 : (total_blue > MaxRGB) ? MaxRGB : total_blue),
255);
p++;
p2++;
p3++;
q++;
}
p++;
*q++=(*(cTable+(*p)));
}
}
toGray(dest);
normalize(dest);
return(dest);
}
QImage OImageEffect::shade(QImage &src, bool color_shading, double azimuth,
double elevation)
{
struct PointInfo{
double x, y, z;
};
double distance, normal_distance, shade;
int x, y;
struct PointInfo light, normal;
unsigned int *q;
QImage dest(src.width(), src.height(), 32);
azimuth = DegreesToRadians(azimuth);
elevation = DegreesToRadians(elevation);
light.x = MaxRGB*cos(azimuth)*cos(elevation);
light.y = MaxRGB*sin(azimuth)*cos(elevation);
light.z = MaxRGB*sin(elevation);
normal.z= 2*MaxRGB; // constant Z of surface normal
if(src.depth() > 8){ // DirectClass source image
unsigned int *p, *s0, *s1, *s2;
for(y=0; y < src.height(); ++y){
p = (unsigned int *)src.scanLine(QMIN(QMAX(y-1,0),src.height()-3));
q = (unsigned int *)dest.scanLine(y);
// shade this row of pixels.
*q++=(*(p+src.width()));
p++;
s0 = p;
s1 = p + src.width();
s2 = p + 2*src.width();
for(x=1; x < src.width()-1; ++x){
// determine the surface normal and compute shading.
normal.x=intensityValue(*(s0-1))+intensityValue(*(s1-1))+intensityValue(*(s2-1))-
(double) intensityValue(*(s0+1))-(double) intensityValue(*(s1+1))-
(double) intensityValue(*(s2+1));
normal.y=intensityValue(*(s2-1))+intensityValue(*s2)+intensityValue(*(s2+1))-
(double) intensityValue(*(s0-1))-(double) intensityValue(*s0)-
(double) intensityValue(*(s0+1));
if((normal.x == 0) && (normal.y == 0))
shade=light.z;
else{
shade=0.0;
distance=normal.x*light.x+normal.y*light.y+normal.z*light.z;
if (distance > 0.0){
normal_distance=
normal.x*normal.x+normal.y*normal.y+normal.z*normal.z;
if(fabs(normal_distance) > 0.0000001)
shade=distance/sqrt(normal_distance);
}
}
if(!color_shading){
*q = qRgba((unsigned char)(shade),
(unsigned char)(shade),
(unsigned char)(shade),
qAlpha(*s1));
}
else{
*q = qRgba((unsigned char)((shade*qRed(*s1))/(MaxRGB+1)),
(unsigned char)((shade*qGreen(*s1))/(MaxRGB+1)),
(unsigned char)((shade*qBlue(*s1))/(MaxRGB+1)),
qAlpha(*s1));
}
++s0;
++s1;
++s2;
q++;
}
*q++=(*s1);
}
}
else{ // PsudeoClass source image
unsigned char *p, *s0, *s1, *s2;
int scanLineIdx;
unsigned int *cTable = (unsigned int *)src.colorTable();
for(y=0; y < src.height(); ++y){
scanLineIdx = QMIN(QMAX(y-1,0),src.height()-3);
p = (unsigned char *)src.scanLine(scanLineIdx);
q = (unsigned int *)dest.scanLine(y);
// shade this row of pixels.
s0 = p;
s1 = (unsigned char *) src.scanLine(scanLineIdx+1);
s2 = (unsigned char *) src.scanLine(scanLineIdx+2);
*q++=(*(cTable+(*s1)));
++p;
++s0;
++s1;
++s2;
for(x=1; x < src.width()-1; ++x){
// determine the surface normal and compute shading.
normal.x=intensityValue(*(cTable+(*(s0-1))))+intensityValue(*(cTable+(*(s1-1))))+intensityValue(*(cTable+(*(s2-1))))-
(double) intensityValue(*(cTable+(*(s0+1))))-(double) intensityValue(*(cTable+(*(s1+1))))-
diff --git a/libopie2/opieui/olistview.cpp b/libopie2/opieui/olistview.cpp
index ec503dd..38f3fe2 100644
--- a/libopie2/opieui/olistview.cpp
+++ b/libopie2/opieui/olistview.cpp
@@ -1,613 +1,613 @@
/*
                This file is part of the Opie Project
-
- =. (C) 2003 Michael 'Mickey' Lauer <mickey@tm.informatik.uni-frankfurt.de>
+ =. (C) 2003 Michael 'Mickey' Lauer <mickey@Vanille.de>
.=l.
           .>+-=
 _;:,     .>    :=|. This program is free software; you can
.> <`_,   >  .   <= redistribute it and/or modify it under
:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
.="- .-=="i,     .._ License as published by the Free Software
 - .   .-<_>     .<> Foundation; either version 2 of the License,
     ._= =}       : or (at your option) any later version.
    .%`+i>       _;_.
    .i_,=:_.      -<s. 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
..}^=.=       =       ; Library General Public License for more
++=   -.     .`     .: details.
 :     =  ...= . :.=-
 -.   .:....=;==+<; You should have received a copy of the GNU
  -_. . .   )=.  = Library General Public License along with
    --        :-=` this library; see the file COPYING.LIB.
If not, write to the Free Software Foundation,
Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
*/
/* QT */
#include <qcolor.h>
#include <qheader.h>
#include <qpainter.h>
#include <qpixmap.h>
/* OPIE */
+#include <opie2/odebug.h>
#include <opie2/olistview.h>
/*======================================================================================
* OListView
*======================================================================================*/
OListView::OListView( QWidget *parent, const char *name )
:QListView( parent, name )
{
//FIXME: get from global settings and calculate ==> see oglobalsettings.*
m_alternateBackground = QColor( 238, 246, 255 );
m_columnSeparator = QPen( QColor( 150, 160, 170 ), 0, DotLine );
m_fullWidth = true;
connect( this, SIGNAL(expanded(QListViewItem*)), SLOT(expand(QListViewItem*)));
}
OListView::~OListView()
{
}
void OListView::setFullWidth( bool fullWidth )
{
m_fullWidth = m_fullWidth;
#if QT_VERSION > 290
header()->setStretchEnabled( fullWidth, columns()-1 );
#endif
}
bool OListView::fullWidth() const
{
return m_fullWidth;
}
int OListView::addColumn( const QString& label, int width )
{
int result = QListView::addColumn( label, width );
#if QT_VERSION > 290
if (m_fullWidth) {
header()->setStretchEnabled( false, columns()-2 );
header()->setStretchEnabled( true, columns()-1 );
}
#endif
return result;
}
int OListView::addColumn( const QIconSet& iconset, const QString& label, int width )
{
int result = QListView::addColumn( iconset, label, width );
#if QT_VERSION > 290
if (m_fullWidth) {
header()->setStretchEnabled( false, columns()-2 );
header()->setStretchEnabled( true, columns()-1 );
}
#endif
return result;
}
void OListView::removeColumn( int index )
{
QListView::removeColumn(index);
#if QT_VERSION > 290
if ( m_fullWidth && index == columns() )
{
header()->setStretchEnabled( true, columns()-1 );
}
#endif
}
const QColor& OListView::alternateBackground() const
{
return m_alternateBackground;
}
void OListView::setAlternateBackground( const QColor &c )
{
m_alternateBackground = c;
repaint();
}
const QPen& OListView::columnSeparator() const
{
return m_columnSeparator;
}
void OListView::setColumnSeparator( const QPen& p )
{
m_columnSeparator = p;
repaint();
}
void OListView::expand(QListViewItem *item)
{
((OListViewItem*)item)->expand();
}
OListViewItem* OListView::childFactory()
{
return new OListViewItem( this );
}
#ifndef QT_NO_DATASTREAM
void OListView::serializeTo( QDataStream& s ) const
{
#warning Caution... the binary format is still under construction...
- qDebug( "storing OListView..." );
+ odebug << "storing OListView..." << oendl;
// store number of columns and the labels
s << columns();
for ( int i = 0; i < columns(); ++i )
s << columnText( i );
// calculate the number of top-level items to serialize
int items = 0;
QListViewItem* item = firstChild();
while ( item )
{
item = item->nextSibling();
items++;
}
// store number of items and the items itself
s << items;
item = firstChild();
for ( int i = 0; i < items; ++i )
{
s << *static_cast<OListViewItem*>( item );
item = item->nextSibling();
}
- qDebug( "OListview stored." );
+ odebug << "OListview stored." << oendl;
}
void OListView::serializeFrom( QDataStream& s )
{
#warning Caution... the binary format is still under construction...
- qDebug( "loading OListView..." );
+ odebug << "loading OListView..." << oendl;
int cols;
s >> cols;
qDebug( "read number of columns = %d", cols );
while ( columns() < cols ) addColumn( QString::null );
for ( int i = 0; i < cols; ++i )
{
QString coltext;
s >> coltext;
qDebug( "read text '%s' for column %d", (const char*) coltext, i );
setColumnText( i, coltext );
}
int items;
s >> items;
qDebug( "read number of items = %d", items );
for ( int i = 0; i < items; ++i )
{
OListViewItem* item = childFactory();
s >> *item;
}
- qDebug( "OListView loaded." );
+ odebug << "OListView loaded." << oendl;
}
QDataStream& operator<<( QDataStream& s, const OListView& lv )
{
lv.serializeTo( s );
}
QDataStream& operator>>( QDataStream& s, OListView& lv )
{
lv.serializeFrom( s );
}
#endif // QT_NO_DATASTREAM
/*======================================================================================
* OListViewItem
*======================================================================================*/
OListViewItem::OListViewItem(QListView *parent)
: QListViewItem(parent)
{
init();
}
OListViewItem::OListViewItem(QListViewItem *parent)
: QListViewItem(parent)
{
init();
}
OListViewItem::OListViewItem(QListView *parent, QListViewItem *after)
: QListViewItem(parent, after)
{
init();
}
OListViewItem::OListViewItem(QListViewItem *parent, QListViewItem *after)
: QListViewItem(parent, after)
{
init();
}
OListViewItem::OListViewItem(QListView *parent,
QString label1, QString label2, QString label3, QString label4,
QString label5, QString label6, QString label7, QString label8)
: QListViewItem(parent, label1, label2, label3, label4, label5, label6, label7, label8)
{
init();
}
OListViewItem::OListViewItem(QListViewItem *parent,
QString label1, QString label2, QString label3, QString label4,
QString label5, QString label6, QString label7, QString label8)
: QListViewItem(parent, label1, label2, label3, label4, label5, label6, label7, label8)
{
init();
}
OListViewItem::OListViewItem(QListView *parent, QListViewItem *after,
QString label1, QString label2, QString label3, QString label4,
QString label5, QString label6, QString label7, QString label8)
: QListViewItem(parent, after, label1, label2, label3, label4, label5, label6, label7, label8)
{
init();
}
OListViewItem::OListViewItem(QListViewItem *parent, QListViewItem *after,
QString label1, QString label2, QString label3, QString label4,
QString label5, QString label6, QString label7, QString label8)
: QListViewItem(parent, after, label1, label2, label3, label4, label5, label6, label7, label8)
{
init();
}
OListViewItem::~OListViewItem()
{
}
void OListViewItem::init()
{
m_known = false;
}
const QColor &OListViewItem::backgroundColor()
{
return isAlternate() ? static_cast<OListView*>(listView())->alternateBackground() :
listView()->viewport()->colorGroup().base();
}
bool OListViewItem::isAlternate()
{
OListView *lv = static_cast<OListView*>( listView() );
// check if the item above is an OListViewItem
OListViewItem *above = static_cast<OListViewItem*>( itemAbove() );
/*if (! itemAbove()->inherits( "OListViewItem" )) return false;*/
// check if we have a valid alternate background color
if (!(lv && lv->alternateBackground().isValid())) return false;
m_known = above ? above->m_known : true;
if (m_known)
{
m_odd = above ? !above->m_odd : false;
}
else
{
OListViewItem *item;
bool previous = true;
if (parent())
{
item = static_cast<OListViewItem *>(parent());
if ( item /*&& item->inherits( "OListViewItem" )*/ ) previous = item->m_odd;
item = static_cast<OListViewItem *>(parent()->firstChild());
/* if ( !item.inherits( "OListViewItem" ) item = 0; */
}
else
{
item = static_cast<OListViewItem *>(lv->firstChild());
}
while(item)
{
item->m_odd = previous = !previous;
item->m_known = true;
item = static_cast<OListViewItem *>(item->nextSibling());
/* if (!item.inherits( "OListViewItem" ) ) break; */
}
}
return m_odd;
}
void OListViewItem::paintCell(QPainter *p, const QColorGroup &cg, int column, int width, int alignment)
{
QColorGroup _cg = cg;
const QPixmap *pm = listView()->viewport()->backgroundPixmap();
if (pm && !pm->isNull())
{
_cg.setBrush( QColorGroup::Base, QBrush(backgroundColor(), *pm) );
p->setBrushOrigin( -listView()->contentsX(), -listView()->contentsY() );
}
else if ( isAlternate() )
{
_cg.setColor( QColorGroup::Base, static_cast<OListView*>( listView() )->alternateBackground() );
}
QListViewItem::paintCell( p, _cg, column, width, alignment );
//FIXME: Use styling here!
const QPen& pen = static_cast<OListView*>( listView() )->columnSeparator();
p->setPen( pen );
p->drawLine( width-1, 0, width-1, height() );
}
OListViewItem* OListViewItem::childFactory()
{
return new OListViewItem( this );
}
#ifndef QT_NO_DATASTREAM
void OListViewItem::serializeTo( QDataStream& s ) const
{
#warning Caution... the binary format is still under construction...
- qDebug( "storing OListViewItem..." );
+ odebug << "storing OListViewItem..." << oendl;
// store item text
for ( int i = 0; i < listView()->columns(); ++i )
{
s << text( i );
}
// calculate the number of children to serialize
int items = 0;
QListViewItem* item = firstChild();
while ( item )
{
item = item->nextSibling();
items++;
}
// store number of items and the items itself
s << items;
item = firstChild();
for ( int i = 0; i < items; ++i )
{
s << *static_cast<OListViewItem*>( item );
item = item->nextSibling();
}
- qDebug( "OListviewItem stored." );
+ odebug << "OListviewItem stored." << oendl;
}
void OListViewItem::serializeFrom( QDataStream& s )
{
#warning Caution... the binary format is still under construction...
- qDebug( "loading OListViewItem..." );
+ odebug << "loading OListViewItem..." << oendl;
for ( int i = 0; i < listView()->columns(); ++i )
{
QString coltext;
s >> coltext;
qDebug( "read text '%s' for column %d", (const char*) coltext, i );
setText( i, coltext );
}
int items;
s >> items;
qDebug( "read number of items = %d", items );
for ( int i = 0; i < items; ++i )
{
OListViewItem* item = childFactory();
s >> (*item);
}
- qDebug( "OListViewItem loaded." );
+ odebug << "OListViewItem loaded." << oendl;
}
QDataStream& operator<<( QDataStream& s, const OListViewItem& lvi )
{
lvi.serializeTo( s );
}
QDataStream& operator>>( QDataStream& s, OListViewItem& lvi )
{
lvi.serializeFrom( s );
}
#endif // QT_NO_DATASTREAM
/*======================================================================================
* ONamedListView
*======================================================================================*/
ONamedListView::ONamedListView( QWidget *parent, const char *name )
:OListView( parent, name )
{
}
ONamedListView::~ONamedListView()
{
}
void ONamedListView::addColumns( const QStringList& columns )
{
for ( QStringList::ConstIterator it = columns.begin(); it != columns.end(); ++it )
{
qDebug( "adding column %s", (const char*) *it );
addColumn( *it );
}
}
int ONamedListView::findColumn( const QString& text ) const
{
//FIXME: If used excessively, this will slow down performance of updates
//FIXME: because of the linear search over all column texts.
//FIXME: I will optimize later by using a hash map.
for ( int i = 0; i < columns(); ++i )
if ( columnText( i ) == text )
return i;
return -1;
}
ONamedListViewItem* ONamedListView::find( int column, const QString& text, int recurse ) const
{
return find( (ONamedListViewItem*) firstChild(), column, text, recurse );
}
ONamedListViewItem* ONamedListView::find( ONamedListViewItem* item, int column, const QString& text, int recurse ) const
{
ONamedListViewItem* result;
while ( item && item->text( column ) != text )
{
qDebug( "checked %s", (const char*) item->text( column ) );
if ( recurse < 0 || recurse > 0 )
{
qDebug( "recursion is %d - recursing into...", recurse );
result = find( (ONamedListViewItem*) item->firstChild(), column, text, recurse-1 );
if ( result ) return result;
}
item = (ONamedListViewItem*) item->itemBelow();
}
if ( item && item->text( column ) == text )
return item;
else
return 0;
}
ONamedListViewItem* ONamedListView::find( const QString& column, const QString& text, int recurse ) const
{
int col = findColumn( column );
if ( col != -1 )
return find( (ONamedListViewItem*) firstChild(), col, text, recurse );
else
return 0;
}
ONamedListViewItem* ONamedListView::find( ONamedListViewItem* item, const QString& column, const QString& text, int recurse ) const
{
int col = findColumn( column );
if ( col != -1 )
return find( item, col, text, recurse );
else
return 0;
}
/*======================================================================================
* ONamedListViewItem
*======================================================================================*/
ONamedListViewItem::ONamedListViewItem( QListView* parent, const QStringList& texts )
:OListViewItem( parent )
{
setText( texts );
}
ONamedListViewItem::ONamedListViewItem( QListViewItem* parent, const QStringList& texts )
:OListViewItem( parent )
{
setText( texts );
}
ONamedListViewItem::ONamedListViewItem( QListView* parent, QListViewItem* after, const QStringList& texts )
:OListViewItem( parent, after )
{
setText( texts );
}
ONamedListViewItem::ONamedListViewItem( QListViewItem* parent, QListViewItem* after, const QStringList& texts )
:OListViewItem( parent, after )
{
setText( texts );
}
ONamedListViewItem::~ONamedListViewItem()
{
}
void ONamedListViewItem::setText( const QStringList& texts )
{
int col = 0;
for ( QStringList::ConstIterator it = texts.begin(); it != texts.end(); ++it )
{
qDebug( "setting column %d = text %s", col, (const char*) *it );
OListViewItem::setText( col++, *it );
}
}
void ONamedListViewItem::setText( const QString& column, const QString& text )
{
//FIXME: If used excessively, this will slow down performance of updates
//FIXME: because of the linear search over all column texts.
//FIXME: I will optimize later by using a hash map.
int col = ( (ONamedListView*) listView() )->findColumn( column );
if ( col != -1 )
OListViewItem::setText( col, text );
else
qWarning( "ONamedListViewItem::setText(): Warning! Columntext '%s' not found.", (const char*) column );
}
ONamedListViewItem* ONamedListViewItem::find( int column, const QString& text, int recurse ) const
{
return ( (ONamedListView*) listView() )->find( (ONamedListViewItem*) firstChild(), column, text, recurse );
}
ONamedListViewItem* ONamedListViewItem::find( const QString& column, const QString& text, int recurse ) const
{
int col = ( (ONamedListView*) listView() )->findColumn( column );
if ( col != -1 )
return ( (ONamedListView*) listView() )->find( (ONamedListViewItem*) firstChild(), col, text, recurse );
else
return 0;
}
diff --git a/libopie2/opieui/opieui.pro b/libopie2/opieui/opieui.pro
index b455602..61f9bbb 100644
--- a/libopie2/opieui/opieui.pro
+++ b/libopie2/opieui/opieui.pro
@@ -1,49 +1,47 @@
TEMPLATE = lib
CONFIG += qt warn_on debug
DESTDIR = $(OPIEDIR)/lib
HEADERS = olistview.h \
oimageeffect.h \
opixmapeffect.h \
opopupmenu.h \
opixmapprovider.h \
oselector.h \
oversatileview.h \
oversatileviewitem.h \
odialog.h \
omessagebox.h \
oresource.h \
+ otaskbarapplet.h \
oseparator.h
SOURCES = olistview.cpp \
oimageeffect.cpp \
opixmapeffect.cpp \
opopupmenu.cpp \
opixmapprovider.cpp \
oselector.cpp \
oversatileview.cpp \
oversatileviewitem.cpp \
odialog.cpp \
oresource.cpp \
+ otaskbarapplet.cpp \
oseparator.cpp
INTERFACES =
TARGET = opieui2
VERSION = 1.8.2
+
INCLUDEPATH += $(OPIEDIR)/include
DEPENDPATH += $(OPIEDIR)/include
-LIBS += -lopiecore2
-MOC_DIR = moc
-OBJECTS_DIR = obj
+LIBS += -lopiecore2
!contains( platform, x11 ) {
include ( $(OPIEDIR)/include.pro )
- HEADERS += otaskbarapplet.h
- SOURCES += otaskbarapplet.cpp
}
contains( platform, x11 ) {
LIBS += -L$(OPIEDIR)/lib -Wl,-rpath,$(OPIEDIR)/lib
- message( Warning: NO otaskbarapplet ATM )
}
diff --git a/libopie2/opieui/oseparator.cpp b/libopie2/opieui/oseparator.cpp
index 85181dc..98d42c7 100644
--- a/libopie2/opieui/oseparator.cpp
+++ b/libopie2/opieui/oseparator.cpp
@@ -1,128 +1,128 @@
/*
                This file is part of the Opie Project
-
              Copyright (C) 2003 Michael 'Mickey' Lauer <mickey@tm.informatik.uni-frankfurt.de>
Copyright (C) 1997 Michael Roth <mroth@wirlweb.de>
=.
.=l.
           .>+-=
 _;:,     .>    :=|. This program is free software; you can
.> <`_,   >  .   <= redistribute it and/or modify it under
:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
.="- .-=="i,     .._ License as published by the Free Software
 - .   .-<_>     .<> Foundation; either version 2 of the License,
     ._= =}       : or (at your option) any later version.
    .%`+i>       _;_.
    .i_,=:_.      -<s. 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
..}^=.=       =       ; Library General Public License for more
++=   -.     .`     .: details.
 :     =  ...= . :.=-
 -.   .:....=;==+<; You should have received a copy of the GNU
  -_. . .   )=.  = Library General Public License along with
    --        :-=` this library; see the file COPYING.LIB.
If not, write to the Free Software Foundation,
Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
*/
-/* QT */
-
-#include <qstyle.h>
-
/* OPIE */
+#include <opie2/odebug.h>
#include <opie2/oseparator.h>
+/* QT */
+
+#include <qstyle.h>
+
OSeparator::OSeparator(QWidget* parent, const char* name, WFlags f)
: QFrame(parent, name, f)
{
setLineWidth(1);
setMidLineWidth(0);
setOrientation( HLine );
}
OSeparator::OSeparator(int orientation, QWidget* parent, const char* name, WFlags f)
: QFrame(parent, name, f)
{
setLineWidth(1);
setMidLineWidth(0);
setOrientation( orientation );
}
void OSeparator::setOrientation(int orientation)
{
switch(orientation)
{
case Vertical:
case VLine:
setFrameStyle( QFrame::VLine | QFrame::Sunken );
setMinimumSize(2, 0);
break;
default:
- qWarning( "OSeparator::setOrientation(): invalid orientation, using default orientation HLine" );
+ owarn << "OSeparator::setOrientation(): invalid orientation, using default orientation HLine" << oendl;
case Horizontal:
case HLine:
setFrameStyle( QFrame::HLine | QFrame::Sunken );
setMinimumSize(0, 2);
break;
}
}
int OSeparator::orientation() const
{
if ( frameStyle() & VLine )
return VLine;
if ( frameStyle() & HLine )
return HLine;
return 0;
}
void OSeparator::drawFrame(QPainter *p)
{
QPoint p1, p2;
QRect r = frameRect();
const QColorGroup & g = colorGroup();
if ( frameStyle() & HLine ) {
p1 = QPoint( r.x(), r.height()/2 );
p2 = QPoint( r.x()+r.width(), p1.y() );
}
else {
p1 = QPoint( r.x()+r.width()/2, 0 );
p2 = QPoint( p1.x(), r.height() );
}
#if QT_VERSION < 300
style().drawSeparator( p, p1.x(), p1.y(), p2.x(), p2.y(), g, true, 1, midLineWidth() );
#else
QStyleOption opt( lineWidth(), midLineWidth() );
style().drawPrimitive( QStyle::PE_Separator, p, QRect( p1, p2 ), g, QStyle::Style_Sunken, opt );
#endif
}
QSize OSeparator::sizeHint() const
{
if ( frameStyle() & VLine )
return QSize(2, 0);
if ( frameStyle() & HLine )
return QSize(0, 2);
return QSize(-1, -1);
}
diff --git a/libopie2/opieui/oversatileview.cpp b/libopie2/opieui/oversatileview.cpp
index 6808539..65fe3d8 100644
--- a/libopie2/opieui/oversatileview.cpp
+++ b/libopie2/opieui/oversatileview.cpp
@@ -1,963 +1,964 @@
/*
                This file is part of the Opie Project
=. (C) 2003 Michael 'Mickey' Lauer <mickey@tm.informatik.uni-frankfurt.de>
.=l.
           .>+-=
 _;:,     .>    :=|. This program is free software; you can
.> <`_,   >  .   <= redistribute it and/or modify it under
:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
.="- .-=="i,     .._ License as published by the Free Software
 - .   .-<_>     .<> Foundation; either version 2 of the License,
     ._= =}       : or (at your option) any later version.
    .%`+i>       _;_.
    .i_,=:_.      -<s. 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
..}^=.=       =       ; Library General Public License for more
++=   -.     .`     .: details.
 :     =  ...= . :.=-
 -.   .:....=;==+<; You should have received a copy of the GNU
  -_. . .   )=.  = Library General Public License along with
    --        :-=` this library; see the file COPYING.LIB.
If not, write to the Free Software Foundation,
Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
*/
+/* OPIE */
+
+#include <opie2/odebug.h>
+#include <opie2/oversatileview.h>
+#include <opie2/oversatileviewitem.h>
+#include <opie2/olistview.h>
+
/* QT */
#include <qaction.h>
#include <qbrush.h>
#include <qfont.h>
#include <qiconset.h>
#include <qiconview.h>
#include <qlistview.h>
#include <qpalette.h>
#include <qpoint.h>
#include <qpopupmenu.h>
#include <qrect.h>
#include <qsize.h>
#include <qstring.h>
#include <qwidgetstack.h>
-/* OPIE */
-
-#include <opie2/oversatileview.h>
-#include <opie2/oversatileviewitem.h>
-#include <opie2/olistview.h>
-
/* XPM */
static const char * view_icon_xpm[] = {
"16 16 16 1",
" c None",
". c #87BD88",
"+ c #8BBE8B",
"@ c #81BA81",
"# c #6DAF6D",
"$ c #87BD87",
"% c #FCFDFC",
"& c #AED0AE",
"* c #4E9C4C",
"= c #91BD91",
"- c #72B172",
"; c #448643",
"> c #519F50",
", c #499247",
"' c #356A35",
") c #686868",
" ",
" .+@# .+@# ",
" $%&* $%&* ",
" @=-; @=-; ",
" #>,' #>,' ",
" ",
" )))))) )))))) ",
" ",
" ",
" .+@# .+@# ",
" $%&* $%&* ",
" @=-; @=-; ",
" #>,' #>,' ",
" ",
" )))))) )))))) ",
" "};
/* XPM */
static const char * view_tree_xpm[] = {
"16 16 17 1",
" c None",
". c #3A3A3A",
"+ c #87BD88",
"@ c #8BBE8B",
"# c #81BA81",
"$ c #6DAF6D",
"% c #87BD87",
"& c #FCFDFC",
"* c #AED0AE",
"= c #4E9C4C",
"- c #91BD91",
"; c #72B172",
"> c #448643",
", c #686868",
"' c #519F50",
") c #499247",
"! c #356A35",
" . ",
" . ",
" . +@#$ ",
" . %&*= ",
" .. #-;> ,, ,,,",
" . $')! ",
" . ",
" . ",
" . ",
" . +@#$ ",
" . %&*= ",
" .. #-;> ,, ,,,",
" $')! ",
" ",
" ",
" "};
OVersatileView::OVersatileView( QWidget* parent, const char* name, int mode )
:QWidgetStack( parent, name ),
_viewmode( mode ), _warningpolicy( None ),
_treeleaf(), _treeopened(), _treeclosed(),
_iconleaf(), _iconopened(), _iconclosed()
{
//
// Create child widgets and set some reasonable default styles
//
_listview = new OListView( this, "oversatileview embedded listview" );
_iconview = new QIconView( this, "oversatileview embedded iconview" );
_listview->setAllColumnsShowFocus( true );
_listview->setRootIsDecorated( true );
_listview->setShowSortIndicator( true );
_iconview->setGridX( 90 );
_iconview->setGridY( 42 );
_iconview->setAutoArrange( true );
#ifdef QWS // TODO: Let this depend on current geometry (rotation)
_iconview->setArrangement( QIconView::TopToBottom );
#else
_iconview->setArrangement( QIconView::LeftToRight );
#endif
_iconview->setResizeMode( QIconView::Adjust );
// qt-embedded: map stylus right on hold to right button press
#ifdef QWS
( (QPEApplication*) qApp)->setStylusOperation( _iconview->viewport(), QPEApplication::RightOnHold );
( (QPEApplication*) qApp)->setStylusOperation( _listview->viewport(), QPEApplication::RightOnHold );
#endif
setViewMode( mode ); // TODO: Read last style from config
// setSynchronization( true ); // TODO: Implement this
// create context menu allowing to switch between the views
_contextmenu = new QPopupMenu( 0, "oversatileview contextmenu" );
_contextmenu->setCaption( "Style" );
_contextmenu->setCheckable( true );
QActionGroup* ag = new QActionGroup( _contextmenu, "style option group" );
QAction* a1 = new QAction( "View Items in Icon Style", QIconSet( QPixmap( view_icon_xpm ) ),
"View Icons", 0, ag, "viewicon action", true );
QAction* a2 = new QAction( "View Items in Tree Style", QIconSet( QPixmap( view_tree_xpm ) ),
"View Tree", 0, ag, "viewtree action", true );
ag->addTo( _contextmenu );
if ( mode == Icons )
a1->setOn( true );
else if ( mode == Tree )
a2->setOn( true );
connect( a1, SIGNAL( activated() ), this, SLOT( setIconViewMode() ) );
connect( a2, SIGNAL( activated() ), this, SLOT( setTreeViewMode() ) );
#if (QT_VERSION >= 0x030000)
connect( _listview, SIGNAL( contextMenuRequested( QListViewItem*, const QPoint&, int ) ), this, SLOT( contextMenuRequested( QListViewItem*, const QPoint&, int ) ) );
connect( _iconview, SIGNAL( contextMenuRequested( QIconViewItem*, const QPoint& ) ), this, SLOT( contextMenuRequested( QIconViewItem*, const QPoint& ) ) );
#else
connect( _listview, SIGNAL( rightButtonPressed( QListViewItem*, const QPoint&, int ) ), this, SLOT( contextMenuRequested( QListViewItem*, const QPoint&, int ) ) );
connect( _iconview, SIGNAL( rightButtonPressed( QIconViewItem*, const QPoint& ) ), this, SLOT( contextMenuRequested( QIconViewItem*, const QPoint& ) ) );
#endif
//
// signal forwarders
//
// unfortunately we can't short-circuit all the QListView and QIconView signals
// to OVersatileView signals, because the signal/slot mechanism doesn't allow
// type-conversion :-(
// common signals for listview
connect( _listview, SIGNAL( selectionChanged() ), this, SIGNAL( selectionChanged() ) );
connect( _listview, SIGNAL( selectionChanged( QListViewItem * ) ), this, SLOT( selectionChanged( QListViewItem * ) ) );
connect( _listview, SIGNAL( currentChanged( QListViewItem * ) ), this, SLOT( currentChanged( QListViewItem * ) ) );
connect( _listview, SIGNAL( clicked( QListViewItem * ) ), this, SLOT( clicked( QListViewItem * ) ) );
connect( _listview, SIGNAL( pressed( QListViewItem * ) ), this, SLOT( pressed( QListViewItem * ) ) );
connect( _listview, SIGNAL( doubleClicked( QListViewItem * ) ), this, SLOT( doubleClicked( QListViewItem * ) ) );
connect( _listview, SIGNAL( returnPressed( QListViewItem * ) ), this, SLOT( returnPressed( QListViewItem * ) ) );
connect( _listview, SIGNAL( onItem( QListViewItem * ) ), this, SLOT( onItem( QListViewItem * ) ) );
connect( _listview, SIGNAL( onViewport() ), this, SIGNAL( onViewport() ) );
// common signals for iconview
connect( _iconview, SIGNAL( selectionChanged() ), this, SIGNAL( selectionChanged() ) );
connect( _iconview, SIGNAL( selectionChanged( QIconViewItem * ) ), this, SLOT( selectionChanged( QIconViewItem * ) ) );
connect( _iconview, SIGNAL( currentChanged( QIconViewItem * ) ), this, SLOT( currentChanged( QIconViewItem * ) ) );
connect( _iconview, SIGNAL( clicked( QIconViewItem * ) ), this, SLOT( clicked( QIconViewItem * ) ) );
connect( _iconview, SIGNAL( pressed( QIconViewItem * ) ), this, SLOT( pressed( QIconViewItem * ) ) );
connect( _iconview, SIGNAL( doubleClicked( QIconViewItem * ) ), this, SLOT( doubleClicked( QIconViewItem * ) ) );
connect( _iconview, SIGNAL( returnPressed( QIconViewItem * ) ), this, SLOT( returnPressed( QIconViewItem * ) ) );
connect( _iconview, SIGNAL( onItem( QIconViewItem * ) ), this, SLOT( onItem( QIconViewItem * ) ) );
connect( _iconview, SIGNAL( onViewport() ), this, SIGNAL( onViewport() ) );
// listview only signals
connect( _listview, SIGNAL( expanded( QListViewItem * ) ), this, SLOT( expanded( QListViewItem * ) ) );
connect( _listview, SIGNAL( collapsed( QListViewItem * ) ), this, SLOT( collapsed( QListViewItem * ) ) );
// iconview only signals
connect( _iconview, SIGNAL( moved() ), this, SIGNAL( moved() ) );
}
OVersatileView::~OVersatileView()
{
}
QPopupMenu* OVersatileView::contextMenu() const
{
return _contextmenu;
}
void OVersatileView::contextMenuRequested( QListViewItem* item, const QPoint& pos, int col )
{
// can't use QObject::inherits here, because ListViewItems, beit Q, O or K,
// do not inherit from QObject - assuming here the programmer is
// disciplined enough to only add OVersatileViewItems to an OVersatileView
popupContextMenu( static_cast<OVersatileViewItem*>( item ), pos, col );
}
void OVersatileView::contextMenuRequested( QIconViewItem* item, const QPoint& pos )
{
// see above
popupContextMenu( static_cast<OVersatileViewItem*>( item ), pos, -1 );
}
void OVersatileView::popupContextMenu( OVersatileViewItem* item, const QPoint& pos, int col )
{
if ( !item )
_contextmenu->exec( pos );
else
emit( contextMenuRequested( item, pos, col ) );
}
void OVersatileView::setSynchronization( bool sync )
{
_synchronization = sync;
}
bool OVersatileView::synchronization()
{
return _synchronization;
}
void OVersatileView::setDefaultPixmaps( int mode, QPixmap& leaf, QPixmap& opened, QPixmap& closed )
{
if ( mode == Tree )
{
_treeleaf = leaf;
_treeopened = opened;
_treeclosed = closed;
}
else if ( mode == Icons )
{
_iconleaf = leaf;
_iconopened = opened;
_iconclosed = closed;
}
else
{
- qDebug( "OVersatileView::setDefaultPixmaps(): invalid mode" );
+ odebug << "OVersatileView::setDefaultPixmaps(): invalid mode" << oendl;
}
}
QIconView* OVersatileView::iconView() const
{
return _iconview;
}
OListView* OVersatileView::listView() const
{
return _listview;
}
void OVersatileView::setViewMode( int mode )
{
if ( mode == Tree )
{
_viewmode = mode;
raiseWidget( _listview );
}
else if ( mode == Icons )
{
_viewmode = mode;
raiseWidget( _iconview );
}
else
{
- qDebug( "OVersatileView::setViewMode(): invalid mode" );
+ odebug << "OVersatileView::setViewMode(): invalid mode" << oendl;
}
}
void OVersatileView::setIconViewMode()
{
setViewMode( Icons );
}
void OVersatileView::setTreeViewMode()
{
setViewMode( Tree );
}
bool OVersatileView::isValidViewMode( int mode ) const
{
switch ( _warningpolicy )
{
case OVersatileView::None:
{
return true;
}
case OVersatileView::Warn:
{
if ( _viewmode != mode )
{
- qDebug( "OVersatileView::isValidViewMode(): Requested operation not valid in current mode." );
+ odebug << "OVersatileView::isValidViewMode(): Requested operation not valid in current mode." << oendl;
return true;
}
}
case OVersatileView::WarnReturn:
{
if ( _viewmode != mode )
{
- qDebug( "OVersatileView::isValidViewMode(): Requested operation not valid in current mode." );
+ odebug << "OVersatileView::isValidViewMode(): Requested operation not valid in current mode." << oendl;
return false;
}
}
default:
{
- qWarning( "OVersatileView::isValidViewMode(): Inconsistent object state!" );
+ owarn << "OVersatileView::isValidViewMode(): Inconsistent object state!" << oendl;
return true;
}
}
}
void OVersatileView::setWarningPolicy( int policy ) const
{
_warningpolicy = policy;
}
bool OVersatileView::warningPolicy() const
{
return _warningpolicy;
}
//==============================================================================================//
// Stupid Signal forwarders...
// Folks, this is why I like python with its dynamic typing:
// I can code the following dozens of lines C++ in four Python lines...
//==============================================================================================//
void OVersatileView::selectionChanged( QListViewItem * item )
{
emit( selectionChanged( static_cast<OVersatileViewItem*>( item ) ) );
}
void OVersatileView::selectionChanged( QIconViewItem * item )
{
emit( selectionChanged( static_cast<OVersatileViewItem*>( item ) ) );
}
void OVersatileView::currentChanged( QListViewItem * item )
{
emit( currentChanged( static_cast<OVersatileViewItem*>( item ) ) );
}
void OVersatileView::currentChanged( QIconViewItem * item )
{
emit( currentChanged( static_cast<OVersatileViewItem*>( item ) ) );
}
void OVersatileView::clicked( QListViewItem * item )
{
emit( clicked( static_cast<OVersatileViewItem*>( item ) ) );
}
void OVersatileView::clicked( QIconViewItem * item )
{
emit( clicked( static_cast<OVersatileViewItem*>( item ) ) );
}
void OVersatileView::pressed( QListViewItem * item )
{
emit( pressed( static_cast<OVersatileViewItem*>( item ) ) );
}
void OVersatileView::pressed( QIconViewItem * item )
{
emit( pressed( static_cast<OVersatileViewItem*>( item ) ) );
}
void OVersatileView::doubleClicked( QListViewItem * item )
{
emit( doubleClicked( static_cast<OVersatileViewItem*>( item ) ) );
}
void OVersatileView::doubleClicked( QIconViewItem * item )
{
emit( doubleClicked( static_cast<OVersatileViewItem*>( item ) ) );
}
void OVersatileView::returnPressed( QListViewItem * item )
{
emit( returnPressed( static_cast<OVersatileViewItem*>( item ) ) );
}
void OVersatileView::returnPressed( QIconViewItem * item )
{
emit( returnPressed( static_cast<OVersatileViewItem*>( item ) ) );
}
void OVersatileView::onItem( QListViewItem * item )
{
emit( onItem( static_cast<OVersatileViewItem*>( item ) ) );
}
void OVersatileView::onItem( QIconViewItem * item )
{
emit( onItem( static_cast<OVersatileViewItem*>( item ) ) );
}
void OVersatileView::expanded( QListViewItem *item ) // QListView
{
- //qDebug( "OVersatileView::expanded(): opening tree..." );
+ //odebug << "OVersatileView::expanded(): opening tree..." << oendl;
if ( !_treeopened.isNull() )
item->setPixmap( 0, _treeopened );
emit( expanded( static_cast<OVersatileViewItem*>( item ) ) );
}
void OVersatileView::collapsed( QListViewItem *item ) // QListView
{
if ( !_treeclosed.isNull() )
item->setPixmap( 0, _treeclosed );
emit( collapsed( static_cast<OVersatileViewItem*>( item ) ) );
}
//=============================================================================================//
// OVersatileView Case I - API only existing in QListView or QIconView but not in both!
//==============================================================================================//
int OVersatileView::treeStepSize() const // QListView
{
if ( !isValidViewMode( Tree ) )
{
return -1;
}
return _listview->treeStepSize();
}
void OVersatileView::setTreeStepSize( int size ) // QListView
{
if ( !isValidViewMode( Tree ) )
{
return;
}
_listview->setTreeStepSize( size );
}
QHeader * OVersatileView::header() const // QListView
{
if ( !isValidViewMode( Tree ) )
{
return 0;
}
return _listview->header();
}
int OVersatileView::addColumn( const QString &label, int size ) // QListView
{
if ( !isValidViewMode( Tree ) )
{
return -1;
}
return _listview->addColumn( label, size );
}
int OVersatileView::addColumn( const QIconSet& iconset, const QString &label, int size ) // QListView
{
if ( !isValidViewMode( Tree ) )
{
return -1;
}
return _listview->addColumn( iconset, label, size );
}
void OVersatileView::removeColumn( int index ) // QListView
{
if ( !isValidViewMode( Tree ) )
{
return;
}
_listview->removeColumn( index );
}
void OVersatileView::setColumnText( int column, const QString &label ) // QListView
{
if ( !isValidViewMode( Tree ) )
{
return;
}
_listview->setColumnText( column, label );
}
void OVersatileView::setColumnText( int column, const QIconSet& iconset, const QString &label ) // QListView
{
if ( !isValidViewMode( Tree ) )
{
return;
}
_listview->setColumnText( column, iconset, label );
}
QString OVersatileView::columnText( int column ) const // QListView
{
if ( !isValidViewMode( Tree ) )
{
return QString::null;
}
return _listview->columnText( column );
}
void OVersatileView::setColumnWidth( int column, int width ) // QListView
{
if ( !isValidViewMode( Tree ) )
{
return;
}
_listview->setColumnWidth( column, width );
}
int OVersatileView::columnWidth( int column ) const // QListView
{
if ( !isValidViewMode( Tree ) )
{
return -1;
}
return _listview->columnWidth( column );
}
void OVersatileView::setColumnWidthMode( int column, WidthMode mode ) // QListView
{
if ( !isValidViewMode( Tree ) )
{
return;
}
_listview->setColumnWidth( column, mode );
}
int OVersatileView::columns() const // QListView
{
if ( !isValidViewMode( Tree ) )
{
return -1;
}
return _listview->columns();
}
void OVersatileView::setColumnAlignment( int column, int align ) // QListView
{
if ( !isValidViewMode( Tree ) )
{
return;
}
_listview->setColumnAlignment( column, align );
}
int OVersatileView::columnAlignment( int column ) const // QListView
{
if ( !isValidViewMode( Tree ) )
{
return -1;
}
return _listview->columnAlignment( column );
}
OVersatileViewItem * OVersatileView::itemAt( const QPoint & screenPos ) const // QListView
{
if ( !isValidViewMode( Tree ) )
{
return 0;
}
return static_cast<OVersatileViewItem*>( _listview->itemAt( screenPos ) );
}
QRect OVersatileView::itemRect( const OVersatileViewItem * item ) const // QListView
{
if ( !isValidViewMode( Tree ) )
{
return QRect( -1, -1, -1, -1 );
}
return _listview->itemRect( item );
}
int OVersatileView::itemPos( const OVersatileViewItem * item ) // QListView
{
if ( !isValidViewMode( Tree ) )
{
return -1;
}
return _listview->itemPos( item );
}
bool OVersatileView::isSelected( const OVersatileViewItem * item ) const // QListView // also in QIconViewItem but !in QIconView *shrug*
{
if ( !isValidViewMode( Tree ) )
{
return false;
}
return _listview->isSelected( item );
}
void OVersatileView::setMultiSelection( bool enable )
{
_listview->setMultiSelection( enable );
}
bool OVersatileView::isMultiSelection() const
{
return _listview->isMultiSelection();
}
OVersatileViewItem * OVersatileView::selectedItem() const // QListView
{
if ( !isValidViewMode( Tree ) )
{
return 0;
}
return static_cast<OVersatileViewItem*>( _listview->selectedItem() );
}
void OVersatileView::setOpen( OVersatileViewItem * item, bool open ) // QListView
{
if ( !isValidViewMode( Tree ) )
{
return;
}
_listview->setOpen( item, open );
}
bool OVersatileView::isOpen( const OVersatileViewItem * item ) const // QListView
{
if ( !isValidViewMode( Tree ) )
{
return false;
}
return _listview->isOpen( item );
}
OVersatileViewItem * OVersatileView::firstChild() const // QListView
{
if ( !isValidViewMode( Tree ) )
{
return 0;
}
return static_cast<OVersatileViewItem*>( _listview->firstChild() );
}
int OVersatileView::childCount() const // QListView
{
if ( !isValidViewMode( Tree ) )
{
return -1;
}
return _listview->childCount();
}
void OVersatileView::setAllColumnsShowFocus( bool focus ) // QListView
{
if ( !isValidViewMode( Tree ) )
{
return;
}
_listview->setAllColumnsShowFocus( focus );
}
bool OVersatileView::allColumnsShowFocus() const // QListView
{
if ( !isValidViewMode( Tree ) )
{
return false;
}
return _listview->allColumnsShowFocus();
}
void OVersatileView::setItemMargin( int margin ) // QListView
{
if ( !isValidViewMode( Tree ) )
{
return;
}
_listview->setItemMargin( margin );
}
int OVersatileView::itemMargin() const // QListView
{
if ( !isValidViewMode( Tree ) )
{
return -1;
}
return _listview->itemMargin();
}
void OVersatileView::setRootIsDecorated( bool decorate ) // QListView
{
if ( !isValidViewMode( Tree ) )
{
return;
}
_listview->setRootIsDecorated( decorate );
}
bool OVersatileView::rootIsDecorated() const // QListView
{
if ( !isValidViewMode( Tree ) )
{
return false;
}
return _listview->rootIsDecorated();
}
void OVersatileView::setShowSortIndicator( bool show ) // QListView
{
if ( !isValidViewMode( Tree ) )
{
return;
}
_listview->setShowSortIndicator( show );
}
bool OVersatileView::showSortIndicator() const // QListView
{
if ( !isValidViewMode( Tree ) )
{
return false;
}
return _listview->showSortIndicator();
}
void OVersatileView::triggerUpdate() // QListView
{
if ( !isValidViewMode( Tree ) )
{
return;
}
_listview->triggerUpdate();
}
//
// only in QIconView
//
uint OVersatileView::count() const // QIconView
{
if ( !isValidViewMode( Icons ) )
{
return 0;
}
return _iconview->count();
}
int OVersatileView::index( const OVersatileViewItem *item ) const // QIconView
{
if ( !isValidViewMode( Icons ) )
{
return -1;
}
return _iconview->index( item );
}
OVersatileViewItem* OVersatileView::firstItem() const // QIconView
{
if ( !isValidViewMode( Icons ) )
{
return 0;
}
return static_cast<OVersatileViewItem*>( _iconview->firstItem() );
}
OVersatileViewItem* OVersatileView::lastItem() const // QIconView
{
if ( !isValidViewMode( Icons ) )
{
return 0;
}
return static_cast<OVersatileViewItem*>( _iconview->lastItem() );
}
OVersatileViewItem* OVersatileView::findItem( const QPoint &pos ) const // QIconView
{
if ( !isValidViewMode( Icons ) )
{
return 0;
}
return static_cast<OVersatileViewItem*>( _iconview->findItem( pos ) );
}
OVersatileViewItem* OVersatileView::findItem( const QString &text ) const // QIconView
{
if ( !isValidViewMode( Icons ) )
{
return 0;
}
return static_cast<OVersatileViewItem*>( _iconview->findItem( text ) );
}
OVersatileViewItem* OVersatileView::findFirstVisibleItem( const QRect &r ) const // QIconView
{
if ( !isValidViewMode( Icons ) )
{
return 0;
}
return static_cast<OVersatileViewItem*>( _iconview->findFirstVisibleItem( r ) );
}
OVersatileViewItem* OVersatileView::findLastVisibleItem( const QRect &r ) const // QIconView
{
if ( !isValidViewMode( Icons ) )
{
return 0;
}
return static_cast<OVersatileViewItem*>( _iconview->findLastVisibleItem( r ) );
}
void OVersatileView::setGridX( int rx ) // QIconView
{
if ( !isValidViewMode( Icons ) )
{
return;
}
_iconview->setGridX( rx );
}
void OVersatileView::setGridY( int ry ) // QIconView
{
if ( !isValidViewMode( Icons ) )
{
return;
}
_iconview->setGridY( ry );
}
int OVersatileView::gridX() const // QIconView
{
if ( !isValidViewMode( Icons ) )
{
return -1;
}
return _iconview->gridX();
}
int OVersatileView::gridY() const // QIconView
{
if ( !isValidViewMode( Icons ) )
{
return -1;
}
return _iconview->gridY();
}
void OVersatileView::setSpacing( int sp ) // QIconView
{
if ( !isValidViewMode( Icons ) )
{
return;
}
_iconview->setSpacing( sp );
}
int OVersatileView::spacing() const // QIconView
{
if ( !isValidViewMode( Icons ) )
{
return -1;
}
return _iconview->spacing();
}
void OVersatileView::setItemTextPos( QIconView::ItemTextPos pos ) // QIconView
{
if ( !isValidViewMode( Icons ) )
{
return;
}
_iconview->setItemTextPos( pos );
}
QIconView::ItemTextPos OVersatileView::itemTextPos() const // QIconView
{
if ( !isValidViewMode( Icons ) )
{
return (QIconView::ItemTextPos) -1;
}
return _iconview->itemTextPos();
}
void OVersatileView::setItemTextBackground( const QBrush &b ) // QIconView
{
if ( !isValidViewMode( Icons ) )
{
return;
}
_iconview->setItemTextBackground( b );
}
QBrush OVersatileView::itemTextBackground() const // QIconView
{
if ( !isValidViewMode( Icons ) )
{
return QBrush();
}
return _iconview->itemTextBackground();
}
void OVersatileView::setArrangement( QIconView::Arrangement am ) // QIconView
{
if ( !isValidViewMode( Icons ) )
{
return;
}
_iconview->setArrangement( am );
}
QIconView::Arrangement OVersatileView::arrangement() const // QIconView
{
if ( !isValidViewMode( Icons ) )
{
return (QIconView::Arrangement) -1;
}
return _iconview->arrangement();
}
void OVersatileView::setResizeMode( QIconView::ResizeMode am ) // QIconView
{
if ( !isValidViewMode( Icons ) )
{
return;
}
_iconview->setResizeMode( am );
}
QIconView::ResizeMode OVersatileView::resizeMode() const // QIconView
{
if ( !isValidViewMode( Icons ) )
{
return (QIconView::ResizeMode) -1;
}
return _iconview->resizeMode();
}
void OVersatileView::setMaxItemWidth( int w ) // QIconView
{
if ( !isValidViewMode( Icons ) )
{
return;
}
_iconview->setMaxItemWidth( w );
}
int OVersatileView::maxItemWidth() const // QIconView
{
if ( !isValidViewMode( Icons ) )
{
return -1;
}
return _iconview->maxItemWidth();
}
void OVersatileView::setMaxItemTextLength( int w ) // QIconView
{
if ( !isValidViewMode( Icons ) )
{
return;
}
_iconview->setMaxItemTextLength( w );
}