Subversion Repositories Scribus

Rev

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

Rev Author Line No. Line
4430 cbradney 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
*/
3 paul 7
/***************************************************************************
8
                          mspinbox.cpp  -  description
9
                             -------------------
10
    begin                : Sat Jun 16 2001
11
    copyright            : (C) 2001 by Franz Schmid
12
    email                : Franz.Schmid@altmuehlnet.de
13
 ***************************************************************************/
14
 
15
/***************************************************************************
16
 *                                                                         *
17
 *   This program is free software; you can redistribute it and/or modify  *
18
 *   it under the terms of the GNU General Public License as published by  *
19
 *   the Free Software Foundation; either version 2 of the License, or     *
20
 *   (at your option) any later version.                                   *
21
 *                                                                         *
22
 ***************************************************************************/
23
 
24
#include "mspinbox.h"
280 Franz 25
#include "mspinbox.moc"
137 Franz 26
#include <qapplication.h>
333 Franz 27
#include <qlineedit.h>
4112 cbradney 28
#include <qregexp.h>
1568 cbradney 29
#include <cmath>
137 Franz 30
#include "fparser.h"
1568 cbradney 31
#include "units.h"
3 paul 32
 
146 Franz 33
 
3 paul 34
MSpinBox::MSpinBox(QWidget *pa, int s):QSpinBox(pa)
35
{
333 Franz 36
        setParameters(s);
37
        setValidator(0);
38
        ed = editor();
39
        QSpinBox::setLineStep(Decimals);
40
        oldLineStep=0;
41
        readOnly=false;
1617 fschmid 42
        edited = false;
43
    connect( ed, SIGNAL(textChanged(const QString&)), SLOT(textChanged()) );
333 Franz 44
}
45
 
46
MSpinBox::MSpinBox(double minValue, double maxValue, QWidget *pa, int s):QSpinBox(pa)
47
{
48
        setParameters(s);
49
        setValidator(0);
50
        ed = editor();
51
        QSpinBox::setLineStep(Decimals);
52
        oldLineStep=0;
53
        setMinValue(minValue);
54
        setMaxValue(maxValue);
55
        readOnly=false;
1617 fschmid 56
        edited = false;
57
    connect( ed, SIGNAL(textChanged(const QString&)), SLOT(textChanged()) );
333 Franz 58
}
59
 
5087 subik 60
MSpinBox::MSpinBox(QWidget *parent, const char * name): QSpinBox(parent, name)
61
{
5851 subik 62
        setParameters(666); // pv - dummy setup for designer's constructor
5087 subik 63
        setValidator(0);
64
        ed = editor();
5851 subik 65
        QSpinBox::setLineStep(Decimals); // pv - dummy setup for designer's constructor
5087 subik 66
        oldLineStep=0;
67
        readOnly=false;
68
        edited = false;
69
        connect( ed, SIGNAL(textChanged(const QString&)), SLOT(textChanged()) );
70
}
71
 
7920 cbradney 72
MSpinBox::~MSpinBox()
73
{
74
        if (ed)
75
                disconnect( ed, SIGNAL(textChanged(const QString&)));
76
}
77
 
333 Franz 78
void MSpinBox::setParameters( int s )
79
{
1795 cbradney 80
        if (s>=0 && s <=unitGetMaxIndex())
161 Franz 81
        {
1568 cbradney 82
                Width=s;
1569 fschmid 83
                Decimals=static_cast<int>(pow(10, s));
161 Franz 84
        }
1568 cbradney 85
        else
86
        {
87
                Width = 2;
88
                Decimals = 100;
89
        }
1617 fschmid 90
        edited = false;
7920 cbradney 91
        m_tabAdvance = true;
3 paul 92
}
93
 
7884 fschmid 94
void MSpinBox::setTabAdvance(bool enable)
95
{
7920 cbradney 96
        m_tabAdvance = enable;
7884 fschmid 97
}
98
 
3 paul 99
bool MSpinBox::eventFilter( QObject* ob, QEvent* ev )
100
{
2680 cbradney 101
        bool retval = false;
7267 fschmid 102
/* Adding this to be sure that the IM* events are processed correctly i.e not intercepted by our KeyPress/Release handlers */
103
        if ((ev->type() == QEvent::IMStart) || (ev->type() == QEvent::IMCompose) || (ev->type() == QEvent::IMEnd))
104
                return QSpinBox::eventFilter(ob, ev);
3 paul 105
        if ( ev->type() == QEvent::KeyPress )
161 Franz 106
        {
3 paul 107
                QKeyEvent* k = (QKeyEvent*)ev;
5970 cbradney 108
                bool shiftB=k->state() & ShiftButton;
109
                bool controlB=k->state() & ControlButton;
110
                if (k->key() == Key_Shift && !controlB)
161 Franz 111
                {
138 Franz 112
                        setLineStep(QMAX(Decimals / 10, 1));
3 paul 113
                        retval = true;
5970 cbradney 114
                        qApp->sendEvent( this, ev );
3 paul 115
                        return retval;
116
                }
5970 cbradney 117
                else if (k->key() == Key_Control && !shiftB)
3736 fschmid 118
                {
119
                        setLineStep(QMAX(Decimals * 10, 1));
120
                        retval = true;
5970 cbradney 121
                        qApp->sendEvent( this, ev );
3736 fschmid 122
                        return retval;
123
                }
5970 cbradney 124
                else if ((k->key() == Key_Control && shiftB) || (k->key() == Key_Shift && controlB))
125
                {
126
                        setLineStep(QMAX(Decimals / 100, 1));
127
                        retval = true;
128
                        qApp->sendEvent( this, ev );
129
                        return retval;
130
                }
7833 fschmid 131
                else if ((k->key() == Key_Return) || (k->key() == Key_Enter) || (k->key() == Key_Tab))
132
                {
7920 cbradney 133
                        if (!m_tabAdvance)
7884 fschmid 134
                        {
135
                                QSpinBox::interpretText();
136
                                return true;
137
                        }
7833 fschmid 138
                }
161 Franz 139
        }
3736 fschmid 140
        if (ev->type() == QEvent::KeyRelease )
161 Franz 141
        {
3 paul 142
                QKeyEvent* k = (QKeyEvent*)ev;
5970 cbradney 143
                bool shiftB=k->stateAfter() & ShiftButton;
144
                bool controlB=k->stateAfter() & ControlButton;
145
                if ((k->key() == Key_Shift && !controlB) || (k->key() == Key_Control && !shiftB))
161 Franz 146
                {
3 paul 147
                        setLineStep(Decimals);
148
                        retval = true;
161 Franz 149
                    qApp->sendEvent( this, ev );
3 paul 150
                        return retval;
364 Franz 151
                }
5970 cbradney 152
                else if (k->key() == Key_Shift && controlB)
153
                {
154
                        setLineStep(QMAX(Decimals * 10, 1));
155
                        retval = true;
156
                        qApp->sendEvent( this, ev );
157
                        return retval;
158
                }
159
                else if (k->key() == Key_Control && shiftB)
160
                {
161
                        setLineStep(QMAX(Decimals / 10, 1));
162
                        retval = true;
163
                        qApp->sendEvent( this, ev );
164
                        return retval;
165
                }
364 Franz 166
        }
167
        if ( ev->type() == QEvent::Wheel )
168
        {
4013 cbradney 169
                //If read only dont spin
170
                if (readOnly)
171
                        return false;
364 Franz 172
                QWheelEvent* k = (QWheelEvent*)ev;
4027 cbradney 173
                bool shiftB=k->state() & ShiftButton;
174
                bool controlB=k->state() & ControlButton;
175
                if (shiftB && !controlB)
364 Franz 176
                {
177
                        setLineStep(QMAX(Decimals / 10, 1));
178
                        retval = true;
179
                        qApp->sendEvent( this, ev );
180
                        return retval;
3736 fschmid 181
                }
4027 cbradney 182
                else if (!shiftB && controlB)
364 Franz 183
                {
3736 fschmid 184
                        setLineStep(QMAX(Decimals * 10, 1));
185
                        retval = true;
186
                    qApp->sendEvent( this, ev );
187
                        return retval;
188
                }
4027 cbradney 189
                else if (shiftB && controlB)
3736 fschmid 190
                {
4027 cbradney 191
                        setLineStep(QMAX(Decimals / 100, 1));
192
                        retval = true;
193
                    qApp->sendEvent( this, ev );
194
                        return retval;
195
                }
196
                else
197
                if (!shiftB && !controlB)
198
                {
364 Franz 199
                        setLineStep(Decimals);
200
                        retval = true;
201
                        qApp->sendEvent( this, ev );
202
                        return retval;
4027 cbradney 203
                }
161 Franz 204
        }
3 paul 205
        return QSpinBox::eventFilter(ob, ev);
206
}
207
 
208
QString MSpinBox::mapValueToText(int value)
209
{
5405 cbradney 210
        QString s;
5851 subik 211
//      debug outputs for strange designer's behaviour. See (parent, name) constructor for more info - PV
212
//      qDebug("setting s");
213
//      qDebug(QString("params %1 %2 %3 %4<-").arg(value).arg(Decimals).arg(Width).arg(name()));
5405 cbradney 214
        s.setNum(static_cast<double>(value) / Decimals, 'f', Width);
215
        return s;
3 paul 216
}
217
 
218
int MSpinBox::mapTextToValue(bool *)
219
{
161 Franz 220
        FunctionParser fp;
4110 cbradney 221
        setFPConstants(fp);
138 Franz 222
        QString ts = text();
286 Franz 223
        QString su = suffix().stripWhiteSpace();
138 Franz 224
        ts.replace(",", ".");
272 Franz 225
        ts.replace("%", "");
4944 fschmid 226
        int pos = ts.length();
227
        while (pos > 0)
228
        {
229
                pos = ts.findRev(".", pos);
230
                if (pos >= 0)
231
                {
232
                        if (pos < static_cast<int>(ts.length()))
233
                        {
234
                                if (!ts[pos+1].isDigit())
235
                                        ts.insert(pos+1, "0 ");
236
                        }
237
                        pos--;
238
                }
239
        }
240
        if (ts.endsWith("."))
241
                ts.append("0");
4539 cbradney 242
 
4114 cbradney 243
        //Get all our units strings
4539 cbradney 244
        QString trStrPT=unitGetStrFromIndex(SC_PT);
245
        QString trStrMM=unitGetStrFromIndex(SC_MM);
246
        QString trStrIN=unitGetStrFromIndex(SC_IN);
247
        QString trStrP =unitGetStrFromIndex(SC_P);
248
        QString trStrCM=unitGetStrFromIndex(SC_CM);
249
        QString trStrC =unitGetStrFromIndex(SC_C);
250
        QString strPT=unitGetUntranslatedStrFromIndex(SC_PT);
251
        QString strMM=unitGetUntranslatedStrFromIndex(SC_MM);
252
        QString strIN=unitGetUntranslatedStrFromIndex(SC_IN);
253
        QString strP =unitGetUntranslatedStrFromIndex(SC_P);
254
        QString strCM=unitGetUntranslatedStrFromIndex(SC_CM);
255
        QString strC =unitGetUntranslatedStrFromIndex(SC_C);
256
        //CB FParser doesn't handle unicode well/at all.
257
        //So, instead of just getting the translated strings and
258
        //sticking them in as variables in the parser, if they are
259
        //not the same as the untranslated version, then we replace them.
260
        //We lose the ability for now to have some strings in languages 
261
        //that might use them in variables.
262
        //To return to previous functionality, remove the follow replacement ifs,
263
        //S&R in the trStr* assignments trStrPT->strPT and remove the current str* ones. 
264
        //IE, send the translated strings through to the regexp.
265
        if (trStrPT.localeAwareCompare(strPT)!=0)
266
                ts.replace(trStrPT, strPT);
267
        if (trStrMM.localeAwareCompare(strMM)!=0)
268
                ts.replace(trStrMM, strMM);
269
        if (trStrIN.localeAwareCompare(strIN)!=0)
270
                ts.replace(trStrIN, strIN);
271
        if (trStrP.localeAwareCompare(strP)!=0)
272
                ts.replace(trStrP, strP);
273
        if (trStrCM.localeAwareCompare(strCM)!=0)
274
                ts.replace(trStrCM, strCM);
275
        if (trStrC.localeAwareCompare(strPT)!=0)
276
                ts.replace(trStrC, strC);
4114 cbradney 277
        //Replace in our typed text all of the units strings with *unitstring
4112 cbradney 278
        QRegExp rx("\\b(\\d+)\\s*("+strPT+"|"+strP+"|"+strMM+"|"+strC+"|"+strCM+"|"+strIN+")\\b");
4944 fschmid 279
        pos = 0;
4112 cbradney 280
        while (pos >= 0) {
281
                pos = rx.search(ts, pos);
282
                if (pos >= 0) {
283
                        QString replacement = rx.cap(1) + "*" + rx.cap(2);
284
                        ts.replace(pos, rx.cap(0).length(), replacement);
285
                }
286
        }
4114 cbradney 287
        //Get the index of our suffix
288
        int toConvertToIndex=unitIndexFromString(su);
289
        //Add in the fparser constants using our unit strings, and the conversion factors.
290
        fp.AddConstant(strPT, value2value(1.0, SC_PT, toConvertToIndex));
291
        fp.AddConstant(strMM, value2value(1.0, SC_MM, toConvertToIndex));
292
        fp.AddConstant(strIN, value2value(1.0, SC_IN, toConvertToIndex));
293
        fp.AddConstant(strP, value2value(1.0, SC_P, toConvertToIndex));
294
        fp.AddConstant(strCM, value2value(1.0, SC_CM, toConvertToIndex));
295
        fp.AddConstant(strC, value2value(1.0, SC_C, toConvertToIndex));
161 Franz 296
        int ret = fp.Parse(ts.latin1(), "", true);
137 Franz 297
        if (ret >= 0)
298
                return 0;
161 Franz 299
        double erg = fp.Eval(NULL);
139 Franz 300
        return qRound(erg*Decimals);
3 paul 301
}
302
 
1617 fschmid 303
void MSpinBox::textChanged()
304
{
305
        edited = true;
306
}
307
 
308
void MSpinBox::stepDown()
309
{
310
        if ( edited )
311
                QSpinBox::interpretText();
312
        if ( wrapping() && ( QSpinBox::value()-lineStep() < QSpinBox::minValue() ) )
313
                QSpinBox::setValue( QSpinBox::maxValue() - (QSpinBox::maxValue() % lineStep()));
314
        else
315
                QSpinBox::subtractLine();
316
}
317
 
333 Franz 318
void MSpinBox::setValues(double min, double max, int deci, double val)
319
{
320
        setDecimals(deci);
321
        setMinValue(min);
322
        setMaxValue(max);
323
        setValue(val);
1617 fschmid 324
        edited = false;
333 Franz 325
}
326
 
327
void MSpinBox::getValues(double *min, double *max, int *deci, double *val)
328
{
329
        *deci = Decimals;
330
        *min = static_cast<double>(QSpinBox::minValue()) / Decimals;
331
        *max = static_cast<double>(QSpinBox::maxValue()) / Decimals;
332
        *val = static_cast<double>(QSpinBox::value()) / Decimals;
333
}
334
 
3 paul 335
void MSpinBox::setDecimals(int deci)
336
{
337
        Decimals = deci;
146 Franz 338
        QSpinBox::setLineStep(Decimals);
138 Franz 339
        if (deci < 10)
340
                Width = 0;
199 Franz 341
        if ((deci > 9) && (deci < 100))
3 paul 342
                Width = 1;
199 Franz 343
        if ((deci > 99) && (deci < 1000))
3 paul 344
                Width = 2;
199 Franz 345
        if ((deci > 999) && (deci < 10000))
139 Franz 346
                Width = 3;
347
        if (deci > 9999)
348
                Width = 4;
3 paul 349
}
146 Franz 350
 
351
void MSpinBox::setMaxValue(double val)
352
{
353
        QSpinBox::setMaxValue(qRound(val*Decimals));
354
}
355
 
356
void MSpinBox::setMinValue(double val)
357
{
358
        QSpinBox::setMinValue(qRound(val*Decimals));
359
}
360
 
361
void MSpinBox::setValue(double val)
362
{
363
        QSpinBox::setValue(qRound(val*Decimals));
1617 fschmid 364
        edited = false;
146 Franz 365
}
366
 
367
double MSpinBox::value()
368
{
369
        return static_cast<double>(QSpinBox::value()) / Decimals;
370
}
199 Franz 371
 
372
double MSpinBox::minValue()
373
{
374
        return static_cast<double>(QSpinBox::minValue()) / Decimals;
375
}
376
 
377
double MSpinBox::maxValue()
378
{
379
        return static_cast<double>(QSpinBox::maxValue()) / Decimals;
380
}
333 Franz 381
 
382
void MSpinBox::setReadOnly( bool ro )
383
{
335 Franz 384
        if (readOnly!=ro)
385
        {
333 Franz 386
                if (!readOnly && ro) {
387
                        oldLineStep=QSpinBox::lineStep();
388
                        QSpinBox::setLineStep( 0 );
389
                }
390
                else if (readOnly && !ro) {
391
                        QSpinBox::setLineStep( oldLineStep );
392
                        oldLineStep=0;
393
                }
394
                ed->setReadOnly( ro );
335 Franz 395
                readOnly=ro;
333 Franz 396
        }
397
}
398
 
399
bool MSpinBox::isReadOnly() const
400
{
401
        return readOnly;
402
}
403
 
6414 fschmid 404
void MSpinBox::setNewUnit(double oldUnitRatio, double newUnitRatio, int unitIndex)
405
{
406
        double oldVal = value() / oldUnitRatio;
407
        double oldMax = maxValue() / oldUnitRatio;
408
        double oldMin = minValue() / oldUnitRatio;
409
        setSuffix(unitGetSuffixFromIndex(unitIndex));
410
        setDecimals(unitGetDecimalsFromIndex(unitIndex));
411
        setMinValue(oldMin * newUnitRatio);
412
        setMaxValue(oldMax * newUnitRatio);
413
        setValue(oldVal * newUnitRatio);
414
}
415
 
4110 cbradney 416
void MSpinBox::setConstants(const QMap<QString, double>& newConstants)
417
{
418
        functionParserConstants=newConstants;
419
}
420
 
421
void MSpinBox::setFPConstants(FunctionParser &fp)
422
{
423
        if (functionParserConstants.isEmpty())
424
                return;
4112 cbradney 425
 
4115 cbradney 426
        fp.AddConstant("old", static_cast<double>(QSpinBox::value()) / Decimals);
4110 cbradney 427
        QMap<QString, double>::Iterator itend=functionParserConstants.end();
428
        QMap<QString, double>::Iterator it=functionParserConstants.begin();
429
        while(it!=itend)
430
        {
431
                fp.AddConstant(it.key(), it.data());
432
                ++it;
433
        }
434
}