Subversion Repositories Scribus

Rev

Rev 6168 | Rev 6607 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
6129 fschmid 1
/*
2
For general Scribus (>=1.3.2) copyright and licensing information please refer
3
to the COPYING file provided with the program. Following this notice may exist
4
a copyright and/or license notice that predates the release of Scribus 1.3.2
5
for which a new license (GPL+exception) is in place.
6
*/
7
#include "curvewidget.h"
8
#include "curvewidget.moc"
9
 
6130 cbradney 10
#include <cmath>
11
 
6129 fschmid 12
#include <qpushbutton.h>
13
#include <qlabel.h>
14
#include <qlayout.h>
15
#include <qtooltip.h>
16
#include <qwhatsthis.h>
17
#include <qpainter.h>
18
#include <qapplication.h>
19
#include <qcursor.h>
6168 fschmid 20
#include <qmessagebox.h>
6129 fschmid 21
#include "colorutil.h"
6168 fschmid 22
#include "customfdialog.h"
23
#include "util.h"
24
#include "prefsmanager.h"
25
#include "prefsfile.h"
26
#include "commonstrings.h"
6129 fschmid 27
 
28
extern QPixmap loadIcon(QString nam);
29
 
30
KCurve::KCurve(QWidget *parent) : QWidget(parent)
31
{
32
        m_grab_point     = FPoint();
33
        m_dragging = false;
6193 fschmid 34
        m_linear = false;
6129 fschmid 35
        m_pix = NULL;
36
        m_pos = 0;
37
        setMouseTracking(true);
38
        setPaletteBackgroundColor(Qt::NoBackground);
39
        setMinimumSize(150, 150);
40
        m_points.resize(0);
41
        m_points.addPoint(0.0, 0.0);
42
        m_points.addPoint(1.0, 1.0);
43
        setFocusPolicy(QWidget::StrongFocus);
44
}
45
 
46
KCurve::~KCurve()
47
{
48
        if (m_pix) delete m_pix;
49
}
50
 
51
void KCurve::setPixmap(QPixmap pix)
52
{
53
        if (m_pix) delete m_pix;
54
        m_pix = new QPixmap(pix);
55
        repaint(false);
56
}
57
 
58
void KCurve::paintEvent(QPaintEvent *)
59
{
60
        int    x, y;
6149 fschmid 61
        int    wWidth = width() - 1;
62
        int    wHeight = height() - 1;
6129 fschmid 63
        x  = 0;
64
        y  = 0;
65
        // Drawing selection or all histogram values.
66
        // A QPixmap is used for enable the double buffering.
67
        QPixmap pm(size());
68
        QPainter p1;
69
        p1.begin(&pm, this);
70
        //  draw background
71
        if(m_pix)
72
        {
73
                p1.scale(1.0*wWidth/m_pix->width(), 1.0*wHeight/m_pix->height());
74
                p1.drawPixmap(0, 0, *m_pix);
75
                p1.resetXForm();
76
        }
77
        else
78
                pm.fill();
79
        // Draw grid separators.
80
        p1.setPen(QPen::QPen(Qt::gray, 1, Qt::SolidLine));
6131 fschmid 81
        p1.drawLine(wWidth/4, 0, wWidth/4, wHeight);
82
        p1.drawLine(wWidth/2, 0, wWidth/2, wHeight);
83
        p1.drawLine(3*wWidth/4, 0, 3*wWidth/4, wHeight);
84
        p1.drawLine(0, wHeight/4, wWidth, wHeight/4);
85
        p1.drawLine(0, wHeight/2, wWidth, wHeight/2);
86
        p1.drawLine(0, 3*wHeight/4, wWidth, 3*wHeight/4);
6129 fschmid 87
 
88
        // Draw curve.
89
        double curvePrevVal = getCurveValue(0.0);
90
        p1.setPen(QPen::QPen(Qt::black, 1, Qt::SolidLine));
91
        for (x = 0 ; x < wWidth ; x++)
92
        {
93
                double curveX;
94
                double curveVal;
95
                //              curveX = (x + 0.5) / wWidth;
96
                curveX = x / static_cast<double>(wWidth);
97
                curveVal = getCurveValue(curveX);
98
                p1.drawLine(x - 1, wHeight - int(curvePrevVal * wHeight), x,     wHeight - int(curveVal * wHeight));
99
                curvePrevVal = curveVal;
100
        }
101
        p1.drawLine(x - 1, wHeight - int(curvePrevVal * wHeight), x,     wHeight - int(getCurveValue(1.0) * wHeight));
102
        for (uint dh = 0; dh < m_points.size(); dh++)
103
        {
104
                FPoint p = m_points.point(dh);
105
                if(p == m_grab_point)
106
                {
107
                        p1.setPen(QPen::QPen(Qt::red, 3, Qt::SolidLine));
108
                        p1.drawEllipse( int(p.x() * wWidth) - 2, wHeight - 2 - int(p.y() * wHeight), 4, 4 );
109
                }
110
                else
111
                {
112
                        p1.setPen(QPen::QPen(Qt::red, 1, Qt::SolidLine));
113
                        p1.drawEllipse( int(p.x() * wWidth) - 3, wHeight - 3 - int(p.y() * wHeight), 6, 6 );
114
                }
115
        }
116
        p1.end();
117
        bitBlt(this, 0, 0, &pm);
118
}
119
 
120
void KCurve::keyPressEvent(QKeyEvent *e)
121
{
122
        if(e->key() == Qt::Key_Delete || e->key() == Qt::Key_Backspace)
123
        {
124
                if (m_points.size() > 2)
125
                {
126
                        FPoint closest_point;
127
                        FPoint p = m_points.point(0);
128
                        int pos = 0;
129
                        uint cc =0;
130
                        double distance = 1000; // just a big number
131
                        while(cc < m_points.size())
132
                        {
133
                                if (fabs (m_grab_point.x() - p.x()) < distance)
134
                                {
135
                                        distance = fabs(m_grab_point.x() - p.x());
136
                                        closest_point = p;
137
                                        m_pos = pos;
138
                                }
139
                                cc++;
140
                                p = m_points.point(cc);
141
                                pos++;
142
                        }
143
                        FPointArray cli;
144
                        cli.putPoints(0, m_pos, m_points);
145
                        cli.putPoints(cli.size(), m_points.size()-m_pos-1, m_points, m_pos+1);
146
                        m_points.resize(0);
147
                        m_points = cli.copy();
148
                        m_grab_point = closest_point;
149
                        repaint(false);
150
                        emit modified();
151
                        QWidget::keyPressEvent(e);
152
                }
153
        }
154
}
155
 
156
void KCurve::mousePressEvent ( QMouseEvent * e )
157
{
158
        FPoint closest_point = FPoint();
159
        double distance;
160
        if (e->button() != Qt::LeftButton)
161
                return;
162
        double x = e->pos().x() / (float)width();
163
        double y = 1.0 - e->pos().y() / (float)height();
164
        distance = 1000; // just a big number
165
        FPoint p = m_points.point(0);
166
        int insert_pos =0;
167
        int pos = 0;
168
        uint cc =0;
169
        while(cc < m_points.size())
170
        {
171
                if (fabs (x - p.x()) < distance)
172
                {
173
                        distance = fabs(x - p.x());
174
                        closest_point = p;
175
                        insert_pos = pos;
176
                }
177
                cc++;
178
                p = m_points.point(cc);
179
                pos++;
180
        }
181
        m_pos = insert_pos;
182
        m_grab_point = closest_point;
183
        m_grabOffsetX = m_grab_point.x() - x;
184
        m_grabOffsetY = m_grab_point.y() - y;
185
        m_grab_point = FPoint(x + m_grabOffsetX, y + m_grabOffsetY);
186
        double curveVal = getCurveValue(x);
187
        if(distance * width() > 5)
188
        {
189
                m_dragging = false;
190
                if(fabs(y - curveVal) * width() > 5)
191
                        return;
192
                if (m_points.size() < 14)
193
                {
194
                        if (x > closest_point.x())
195
                                m_pos++;
196
                        FPointArray cli;
197
                        cli.putPoints(0, m_pos, m_points);
198
                        cli.resize(cli.size()+1);
199
                        cli.putPoints(cli.size()-1, 1, x, curveVal);
200
                        cli.putPoints(cli.size(), m_points.size()-m_pos, m_points, m_pos);
201
                        m_points.resize(0);
202
                        m_points = cli.copy();
203
                        m_dragging = true;
204
                        m_grab_point = m_points.point(m_pos);
205
                        m_grabOffsetX = m_grab_point.x() - x;
206
                        m_grabOffsetY = m_grab_point.y() - curveVal;
207
                        m_grab_point = FPoint(x + m_grabOffsetX, curveVal + m_grabOffsetY);
208
                        qApp->setOverrideCursor(QCursor(crossCursor), true);
209
                }
210
        }
211
        else
212
        {
213
                if(fabs(y - closest_point.y()) * width() > 5)
214
                        return;
215
                m_dragging = true;
216
                qApp->setOverrideCursor(QCursor(crossCursor), true);
217
        }
218
        // Determine the leftmost and rightmost points.
219
        m_leftmost = 0;
220
        m_rightmost = 1;
6131 fschmid 221
        p = m_points.point(0);
222
        cc = 0;
223
        while(cc < m_points.size())
224
        {
225
                if (p != m_grab_point)
226
                {
227
                        if(p.x() > m_leftmost && p.x() < x)
228
                                m_leftmost = p.x();
229
                        if(p.x() < m_rightmost && p.x() > x)
230
                                m_rightmost = p.x();
231
                }
232
                cc++;
233
                p = m_points.point(cc);
234
    }
6129 fschmid 235
        repaint(false);
236
        emit modified();
237
}
238
 
239
void KCurve::mouseReleaseEvent ( QMouseEvent * e )
240
{
241
        if (e->button() != Qt::LeftButton)
242
                return;
243
        qApp->setOverrideCursor(QCursor(ArrowCursor), true);
244
        m_dragging = false;
245
        repaint(false);
246
        emit modified();
247
}
248
 
249
void KCurve::mouseMoveEvent ( QMouseEvent * e )
250
{
251
        double x = e->pos().x() / (float)width();
252
        double y = 1.0 - e->pos().y() / (float)height();
253
 
254
        if (m_dragging == false)   // If no point is selected set the the cursor shape if on top
255
        {
256
                double distance = 1000;
257
                double ydistance = 1000;
258
                FPoint p = m_points.point(0);
259
                uint cc =0;
260
                while(cc < m_points.size())
261
                {
262
                        if (fabs (x - p.x()) < distance)
263
                        {
264
                                distance = fabs(x - p.x());
265
                                ydistance = fabs(y - p.y());
266
                        }
267
                        cc++;
268
                        p = m_points.point(cc);
269
                }
270
                if (distance * width() > 5 || ydistance * height() > 5)
271
                        qApp->setOverrideCursor(QCursor(ArrowCursor), true);
272
                else
273
                        qApp->setOverrideCursor(QCursor(crossCursor), true);
274
        }
275
        else  // Else, drag the selected point
276
        {
277
                qApp->setOverrideCursor(QCursor(crossCursor), true);
278
                x += m_grabOffsetX;
279
                y += m_grabOffsetY;
280
                if (x <= m_leftmost)
281
                        x = m_leftmost + 1E-4; // the addition so we can grab the dot later.
282
                if(x >= m_rightmost)
283
                        x = m_rightmost - 1E-4;
284
                if(y > 1.0)
285
                        y = 1.0;
286
                if(y < 0.0)
287
                        y = 0.0;
288
                m_grab_point = FPoint(x, y);
289
                m_points.setPoint( m_pos, m_grab_point);
290
                repaint(false);
291
                emit modified();
292
        }
293
}
294
 
295
double KCurve::getCurveValue(double x)
296
{
6193 fschmid 297
        return getCurveYValue(m_points, x, m_linear);
6129 fschmid 298
}
299
 
300
FPointArray KCurve::getCurve()
301
{
302
        return m_points.copy();
303
}
304
 
305
void KCurve::setCurve(FPointArray inlist)
306
{
6131 fschmid 307
        m_points_back = m_points.copy();
6129 fschmid 308
        m_points.resize(0);
309
        m_points = inlist.copy();
310
        repaint(false);
311
        emit modified();
312
}
313
 
6131 fschmid 314
void KCurve::resetCurve()
315
{
316
        m_points.resize(0);
317
        m_points = m_points_back.copy();
318
        repaint(false);
319
        emit modified();
320
}
321
 
6193 fschmid 322
void KCurve::setLinear(bool setter)
323
{
324
        m_linear = setter;
325
        repaint(false);
326
        emit modified();
327
}
328
 
329
bool KCurve::isLinear()
330
{
331
        return m_linear;
332
}
333
 
6129 fschmid 334
void KCurve::leaveEvent( QEvent * )
335
{
336
        qApp->setOverrideCursor(QCursor(ArrowCursor), true);
337
}
338
 
339
CurveWidget::CurveWidget( QWidget* parent ) : QWidget( parent )
340
{
341
        CurveWidgetLayout = new QHBoxLayout( this, 5, 5, "CurveWidgetLayout");
342
 
343
        layout1 = new QVBoxLayout( 0, 0, 5, "layout1");
344
 
345
        invertButton = new QPushButton( this, "invertButton" );
346
        invertButton->setSizePolicy( QSizePolicy( (QSizePolicy::SizeType)0, (QSizePolicy::SizeType)0, 0, 0, invertButton->sizePolicy().hasHeightForWidth() ) );
347
        invertButton->setPixmap( loadIcon("invert.png") );
348
        layout1->addWidget( invertButton );
349
 
350
        resetButton = new QPushButton( this, "resetButton" );
351
        resetButton->setSizePolicy( QSizePolicy( (QSizePolicy::SizeType)0, (QSizePolicy::SizeType)0, 0, 0, resetButton->sizePolicy().hasHeightForWidth() ) );
352
        resetButton->setPixmap( loadIcon("reload.png") );
353
        layout1->addWidget( resetButton );
6193 fschmid 354
        linearButton = new QToolButton( this, "linearButton" );
355
        QIconSet ic;
356
        ic.setPixmap(loadIcon("curvebezier.png"), QIconSet::Automatic, QIconSet::Normal, QIconSet::Off);
357
        ic.setPixmap(loadIcon("curvelinear.png"), QIconSet::Automatic, QIconSet::Normal, QIconSet::On);
358
        linearButton->setIconSet(ic);
359
        linearButton->setToggleButton( true );
360
        linearButton->setOn(false);
361
        layout1->addWidget( linearButton );
6129 fschmid 362
        spacer1 = new QSpacerItem( 21, 31, QSizePolicy::Minimum, QSizePolicy::Expanding );
363
        layout1->addItem( spacer1 );
364
 
365
        loadButton = new QPushButton( this, "loadButton" );
366
        loadButton->setSizePolicy( QSizePolicy( (QSizePolicy::SizeType)0, (QSizePolicy::SizeType)0, 0, 0, loadButton->sizePolicy().hasHeightForWidth() ) );
367
        loadButton->setPixmap( loadIcon("22/document-open.png") );
368
        layout1->addWidget( loadButton );
369
 
370
        saveButton = new QPushButton( this, "saveButton" );
371
        saveButton->setSizePolicy( QSizePolicy( (QSizePolicy::SizeType)0, (QSizePolicy::SizeType)0, 0, 0, saveButton->sizePolicy().hasHeightForWidth() ) );
372
        saveButton->setPixmap( loadIcon("22/document-save-as.png") );
373
        layout1->addWidget( saveButton );
374
        CurveWidgetLayout->addLayout( layout1 );
375
 
376
        cDisplay = new KCurve(this);
377
        cDisplay->setMinimumSize( QSize( 150, 150 ) );
378
        CurveWidgetLayout->addWidget( cDisplay );
379
        languageChange();
380
        clearWState( WState_Polished );
381
        connect(invertButton, SIGNAL(clicked()), this, SLOT(doInvert()));
382
        connect(resetButton, SIGNAL(clicked()), this, SLOT(doReset()));
6193 fschmid 383
        connect(linearButton, SIGNAL(clicked()), this, SLOT(doLinear()));
6168 fschmid 384
        connect(loadButton, SIGNAL(clicked()), this, SLOT(doLoad()));
385
        connect(saveButton, SIGNAL(clicked()), this, SLOT(doSave()));
6129 fschmid 386
}
387
 
388
void CurveWidget::doInvert()
389
{
390
        FPointArray curve = cDisplay->getCurve();
391
        for (uint a = 0; a < curve.size(); a++)
392
        {
393
                FPoint p = curve.point(a);
394
                curve.setPoint(a, p.x(), 1.0 - p.y());
395
        }
396
        cDisplay->setCurve(curve);
397
}
398
 
399
void CurveWidget::doReset()
400
{
6131 fschmid 401
        cDisplay->resetCurve();
6129 fschmid 402
}
403
 
6193 fschmid 404
void CurveWidget::doLinear()
405
{
406
        cDisplay->setLinear(linearButton->isOn());
407
}
408
 
409
void CurveWidget::setLinear(bool setter)
410
{
411
        cDisplay->setLinear(setter);
412
        linearButton->setOn(setter);
413
}
414
 
6168 fschmid 415
void CurveWidget::doLoad()
416
{
417
        QString fileName;
418
        PrefsContext* dirs = PrefsManager::instance()->prefsFile->getContext("dirs");
419
        QString wdir = dirs->get("curves", ".");
420
        CustomFDialog dia(this, wdir, tr("Open"), tr("Curve Files (*.scu);;All Files (*)"));
421
        if (dia.exec() == QDialog::Accepted)
422
                fileName = dia.selectedFile();
423
        else
424
                return;
425
        if (!fileName.isEmpty())
426
        {
427
                if (!fileName.endsWith(".scu"))
428
                        fileName += ".scu";
429
                dirs->set("curves", fileName.left(fileName.findRev("/")));
430
                QFile f(fileName);
431
                if (f.open(IO_ReadOnly))
432
                {
433
                        QTextStream fp(&f);
434
                        int numVals;
435
                        double xval, yval;
436
                        FPointArray curve;
437
                        curve.resize(0);
438
                        fp >> numVals;
439
                        for (int nv = 0; nv < numVals; nv++)
440
                        {
441
                                fp >> xval;
442
                                fp >> yval;
443
                                curve.addPoint(xval, yval);
444
                        }
445
                        cDisplay->setCurve(curve);
6193 fschmid 446
                        int lin;
447
                        fp >> lin;
448
                        cDisplay->setLinear(lin);
6168 fschmid 449
                }
450
        }
451
}
452
 
453
void CurveWidget::doSave()
454
{
455
        QString fileName;
456
        QString wdir = PrefsManager::instance()->prefsFile->getContext("dirs")->get("curves", ".");
457
        CustomFDialog dia(this, wdir, tr("Save as"), tr("Curve Files (*.scu);;All Files (*)"), fdNone);
458
        if (dia.exec() == QDialog::Accepted)
459
                fileName = dia.selectedFile();
460
        else
461
                return;
462
        if (!fileName.isEmpty())
463
        {
464
                PrefsManager::instance()->prefsFile->getContext("dirs")->set("curves", fileName.left(fileName.findRev("/")));
465
                if (overwrite(this, fileName))
466
                {
467
                        QString efval = "";
468
                        FPointArray Vals = cDisplay->getCurve();
469
                        QString tmp;
470
                        tmp.setNum(Vals.size());
471
                        efval += tmp;
472
                        for (uint p = 0; p < Vals.size(); p++)
473
                        {
474
                                FPoint pv = Vals.point(p);
475
                                efval += QString(" %1 %2").arg(pv.x()).arg(pv.y());
476
                        }
6193 fschmid 477
                        if (cDisplay->isLinear())
478
                                efval += " 1";
479
                        else
480
                                efval += " 0";
6168 fschmid 481
                        QFile fx(fileName);
482
                        if (fx.open(IO_WriteOnly))
483
                        {
484
                                QTextStream tsx(&fx);
485
                                tsx << efval;
486
                                fx.close();
487
                        }
488
                        else
489
                                QMessageBox::warning(this, CommonStrings::trWarning, tr("Cannot write the file: \n%1").arg(fileName), CommonStrings::tr_OK);
490
                }
491
        }
492
}
493
 
6129 fschmid 494
/*
495
 *  Sets the strings of the subwidgets using the current
496
 *  language.
497
 */
498
void CurveWidget::languageChange()
499
{
500
        invertButton->setText( QString::null );
501
        resetButton->setText( QString::null );
502
        loadButton->setText( QString::null );
503
        saveButton->setText( QString::null );
6131 fschmid 504
        QToolTip::remove( invertButton );
505
        QToolTip::remove( resetButton );
6193 fschmid 506
        QToolTip::remove( linearButton );
6131 fschmid 507
        QToolTip::remove( loadButton );
508
        QToolTip::remove( saveButton );
509
        QToolTip::add( invertButton, tr( "Inverts the curve" ) );
510
        QToolTip::add( resetButton, tr( "Resets the curve" ) );
6193 fschmid 511
        QToolTip::add( linearButton, tr( "Switches between linear and cubic interpolation of the curve" ) );
6131 fschmid 512
        QToolTip::add( loadButton, tr( "Loads a curve" ) );
513
        QToolTip::add( saveButton, tr( "Saves this curve" ) );
6129 fschmid 514
}
515