Krita Source Code Documentation
Loading...
Searching...
No Matches
rwidgetutils.cpp
Go to the documentation of this file.
1
26#include "rwidgetutils.h"
27
28// Qt includes
29
30#include <QWidget>
31#include <QByteArray>
32#include <QBuffer>
33#include <QImage>
34#include <QHBoxLayout>
35#include <QVBoxLayout>
36#include <QApplication>
37#include <QScreen>
38#include <QPushButton>
39#include <QFileInfo>
40#include <QPainter>
41#include <QStandardPaths>
42#include <QColorDialog>
43#include <QStyleOptionButton>
44#include <qdrawutil.h>
45
46// KDE includes
47
48#include <klocalizedstring.h>
49
50// Local includes
51
52#include "libkdcraw_debug.h"
53
54namespace KDcrawIface
55{
56
57RActiveLabel::RActiveLabel(const QUrl& url, const QString& imgPath, QWidget* const parent)
58 : QLabel(parent)
59{
60 setContentsMargins(0, 0, 0, 0);
61 setScaledContents(false);
62 setOpenExternalLinks(true);
63 setTextFormat(Qt::RichText);
64 setFocusPolicy(Qt::NoFocus);
65 setTextInteractionFlags(Qt::LinksAccessibleByMouse);
66 setSizePolicy(QSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum));
67 QImage img = QImage(imgPath);
68
69 updateData(url, img);
70}
71
75
76void RActiveLabel::updateData(const QUrl& url, const QImage& img)
77{
78 QByteArray byteArray;
79 QBuffer buffer(&byteArray);
80 img.save(&buffer, "PNG");
81 setText(QString::fromLatin1("<a href=\"%1\">%2</a>")
82 .arg(url.url())
83 .arg(QString::fromLatin1("<img src=\"data:image/png;base64,%1\">")
84 .arg(QString::fromLatin1(byteArray.toBase64().data()))));
85}
86
87// ------------------------------------------------------------------------------------
88
89RLineWidget::RLineWidget(Qt::Orientation orientation, QWidget* const parent)
90 : QFrame(parent)
91{
92 setLineWidth(1);
93 setMidLineWidth(0);
94
95 if (orientation == Qt::Vertical)
96 {
97 setFrameShape(QFrame::VLine);
98 setFrameShadow(QFrame::Sunken);
99 setMinimumSize(2, 0);
100 }
101 else
102 {
103 setFrameShape(QFrame::HLine);
104 setFrameShadow(QFrame::Sunken);
105 setMinimumSize(0, 2);
106 }
107
108 updateGeometry();
109}
110
114
115// ------------------------------------------------------------------------------------
116
117RHBox::RHBox(QWidget* const parent)
118 : QFrame(parent)
119{
120 QHBoxLayout* const layout = new QHBoxLayout(this);
121 layout->setSpacing(0);
122 layout->setContentsMargins(0, 0, 0, 0);
123}
124
125RHBox::RHBox(bool /*vertical*/, QWidget* const parent)
126 : QFrame(parent)
127{
128 QVBoxLayout* const layout = new QVBoxLayout(this);
129 layout->setSpacing(0);
130 layout->setContentsMargins(0, 0, 0, 0);
131}
132
134{
135}
136
137void RHBox::childEvent(QChildEvent* e)
138{
139 switch (e->type())
140 {
141 case QEvent::ChildAdded:
142 {
143 QChildEvent* const ce = static_cast<QChildEvent*>(e);
144
145 if (ce->child()->isWidgetType())
146 {
147 QWidget* const w = static_cast<QWidget*>(ce->child());
148 static_cast<QBoxLayout*>(layout())->addWidget(w);
149 }
150
151 break;
152 }
153
154 case QEvent::ChildRemoved:
155 {
156 QChildEvent* const ce = static_cast<QChildEvent*>(e);
157
158 if (ce->child()->isWidgetType())
159 {
160 QWidget* const w = static_cast<QWidget*>(ce->child());
161 static_cast<QBoxLayout*>(layout())->removeWidget(w);
162 }
163
164 break;
165 }
166
167 default:
168 break;
169 }
170
171 QFrame::childEvent(e);
172}
173
174QSize RHBox::sizeHint() const
175{
176 RHBox* const b = const_cast<RHBox*>(this);
177 QApplication::sendPostedEvents(b, QEvent::ChildAdded);
178
179 return QFrame::sizeHint();
180}
181
183{
184 RHBox* const b = const_cast<RHBox*>(this);
185 QApplication::sendPostedEvents(b, QEvent::ChildAdded );
186
187 return QFrame::minimumSizeHint();
188}
189
190void RHBox::setSpacing(int spacing)
191{
192 layout()->setSpacing(spacing);
193}
194
195void RHBox::setMargin(int margin)
196{
197 layout()->setContentsMargins(margin, margin, margin, margin);
198}
199
200void RHBox::setStretchFactor(QWidget* const widget, int stretch)
201{
202 static_cast<QBoxLayout*>(layout())->setStretchFactor(widget, stretch);
203}
204
205// ------------------------------------------------------------------------------------
206
207RVBox::RVBox(QWidget* const parent)
208 : RHBox(true, parent)
209{
210}
211
213{
214}
215
216// ------------------------------------------------------------------------------------
217
218class Q_DECL_HIDDEN RAdjustableLabel::Private
219{
220public:
221
223 {
224 emode = Qt::ElideMiddle;
225 }
226
227 QString ajdText;
228 Qt::TextElideMode emode;
229};
230
232 : QLabel(parent),
233 d(new Private)
234{
235 setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed));
236}
237
242
244{
246}
247
249{
250 QSize sh = QLabel::minimumSizeHint();
251 sh.setWidth(-1);
252 return sh;
253}
254
256{
257 QFontMetrics fm(fontMetrics());
258 QRect geom = geometry();
259 QPoint p(geom.width() / 2 + geom.left(), geom.height() / 2 + geom.top());
260 QScreen *s = qApp->screenAt(p);
261 int maxW;
262 if (s) {
263 maxW = s->availableGeometry().width() * 3 / 4;
264 }
265 else {
266 maxW = 1024;
267 }
268 int currentW = fm.horizontalAdvance(d->ajdText);
269
270 return (QSize(currentW > maxW ? maxW : currentW, QLabel::sizeHint().height()));
271}
272
273void RAdjustableLabel::setAdjustedText(const QString& text)
274{
275 d->ajdText = text;
276
277 if (d->ajdText.isNull())
278 QLabel::clear();
279
281}
282
284{
285 return d->ajdText;
286}
287
288void RAdjustableLabel::setAlignment(Qt::Alignment alignment)
289{
290 QString tmp(d->ajdText);
291 QLabel::setAlignment(alignment);
292 d->ajdText = tmp;
293}
294
295void RAdjustableLabel::setElideMode(Qt::TextElideMode mode)
296{
297 d->emode = mode;
299}
300
302{
303 QFontMetrics fm(fontMetrics());
304 QStringList adjustedLines;
305 int lblW = size().width();
306 bool adjusted = false;
307
308 Q_FOREACH(const QString& line, d->ajdText.split(QLatin1Char('\n')))
309 {
310 int lineW = fm.horizontalAdvance(line);
311 if (lineW > lblW)
312 {
313 adjusted = true;
314 adjustedLines << fm.elidedText(line, d->emode, lblW);
315 }
316 else
317 {
318 adjustedLines << line;
319 }
320 }
321
322 if (adjusted)
323 {
324 QLabel::setText(adjustedLines.join(QStringLiteral("\n")));
325 setToolTip(d->ajdText);
326 }
327 else
328 {
329 QLabel::setText(d->ajdText);
330 setToolTip(QString());
331 }
332}
333
334// ------------------------------------------------------------------------------------
335
336class Q_DECL_HIDDEN RFileSelector::Private
337{
338public:
339
341 {
342 edit = 0;
343 btn = 0;
344 fdMode = QFileDialog::ExistingFile;
345 fdOptions = QFileDialog::DontUseNativeDialog;
346 }
347
348 QLineEdit* edit;
349 QPushButton* btn;
350
351 QFileDialog::FileMode fdMode;
352 QString fdFilter;
353 QString fdTitle;
354 QFileDialog::Options fdOptions;
355};
356
357RFileSelector::RFileSelector(QWidget* const parent)
358 : RHBox(parent),
359 d(new Private)
360{
361 d->edit = new QLineEdit(this);
362 d->btn = new QPushButton(i18n("Browse..."), this);
363 setStretchFactor(d->edit, 10);
364
365 connect(d->btn, SIGNAL(clicked()),
366 this, SLOT(slotBtnClicked()));
367}
368
370{
371 delete d;
372}
373
374QLineEdit* RFileSelector::lineEdit() const
375{
376 return d->edit;
377}
378
379void RFileSelector::setFileDlgMode(QFileDialog::FileMode mode)
380{
381 d->fdMode = mode;
382}
383
384void RFileSelector::setFileDlgFilter(const QString& filter)
385{
386 d->fdFilter = filter;
387}
388
389void RFileSelector::setFileDlgTitle(const QString& title)
390{
391 d->fdTitle = title;
392}
393
394void RFileSelector::setFileDlgOptions(QFileDialog::Options opts)
395{
396 d->fdOptions = opts;
397}
398
400{
401 if (d->fdMode == QFileDialog::ExistingFiles)
402 {
403 qCDebug(LIBKDCRAW_LOG) << "Multiple selection is not supported";
404 return;
405 }
406
407 QFileDialog* const fileDlg = new QFileDialog(this);
408 fileDlg->setOptions(d->fdOptions);
409 fileDlg->setDirectory(QFileInfo(d->edit->text()).dir());
410 fileDlg->setFileMode(d->fdMode);
411
412 if (!d->fdFilter.isNull())
413 fileDlg->setNameFilter(d->fdFilter);
414
415 if (!d->fdTitle.isNull())
416 fileDlg->setWindowTitle(d->fdTitle);
417
418 connect(fileDlg, SIGNAL(urlSelected(QUrl)),
419 this, SIGNAL(signalUrlSelected(QUrl)));
420
421 Q_EMIT signalOpenFileDialog();
422
423 if (fileDlg->exec() == QDialog::Accepted)
424 {
425 QStringList sel = fileDlg->selectedFiles();
426
427 if (!sel.isEmpty())
428 {
429 d->edit->setText(sel.first());
430 }
431 }
432
433 delete fileDlg;
434}
435
436// ---------------------------------------------------------------------------------------
437
439{
440 QPixmap pix(QStandardPaths::locate(QStandardPaths::AppDataLocation, QLatin1String("libkdcraw/pics/process-working.png")));
441 QSize size(22, 22);
442
443 if (pix.isNull())
444 {
445 qCWarning(LIBKDCRAW_LOG) << "Invalid pixmap specified.";
446 return;
447 }
448
449 if (!size.isValid())
450 {
451 size = QSize(pix.width(), pix.width());
452 }
453
454 if (pix.width() % size.width() || pix.height() % size.height())
455 {
456 qCWarning(LIBKDCRAW_LOG) << "Invalid framesize.";
457 return;
458 }
459
460 const int rowCount = pix.height() / size.height();
461 const int colCount = pix.width() / size.width();
462 m_frames.resize(rowCount * colCount);
463
464 int pos = 0;
465
466 for (int row = 0; row < rowCount; ++row)
467 {
468 for (int col = 0; col < colCount; ++col)
469 {
470 QPixmap frm = pix.copy(col * size.width(), row * size.height(), size.width(), size.height());
471 m_frames[pos++] = frm;
472 }
473 }
474}
475
479
481{
482 return m_frames.isEmpty();
483}
484
486{
487 if (isEmpty())
488 {
489 qCWarning(LIBKDCRAW_LOG) << "No frame loaded.";
490 return QSize();
491 }
492
493 return m_frames[0].size();
494}
495
497{
498 return m_frames.size();
499}
500
501QPixmap WorkingPixmap::frameAt(int index) const
502{
503 if (isEmpty())
504 {
505 qCWarning(LIBKDCRAW_LOG) << "No frame loaded.";
506 return QPixmap();
507 }
508
509 return m_frames.at(index);
510}
511
512// ------------------------------------------------------------------------------------
513
514class Q_DECL_HIDDEN RColorSelector::Private
515{
516public:
517
519 {
520 }
521
522 QColor color;
523};
524
525RColorSelector::RColorSelector(QWidget* const parent)
526 : QPushButton(parent),
527 d(new Private)
528{
529 connect(this, SIGNAL(clicked()),
530 this, SLOT(slotBtnClicked()));
531}
532
534{
535 delete d;
536}
537
538void RColorSelector::setColor(const QColor& color)
539{
540 if (color.isValid())
541 {
542 d->color = color;
543 update();
544 }
545}
546
547QColor RColorSelector::color() const
548{
549 return d->color;
550}
551
553{
554 QColor color = QColorDialog::getColor(d->color);
555
556 if (color.isValid())
557 {
560 }
561}
562
564{
565 QPainter painter(this);
566 QStyle* const style = QWidget::style();
567
568 QStyleOptionButton opt;
569
570 opt.initFrom(this);
571 opt.state |= isDown() ? QStyle::State_Sunken : QStyle::State_Raised;
572 opt.features = QStyleOptionButton::None;
573 opt.icon = QIcon();
574 opt.text.clear();
575
576 style->drawControl(QStyle::CE_PushButtonBevel, &opt, &painter, this);
577
578 QRect labelRect = style->subElementRect(QStyle::SE_PushButtonContents, &opt, this);
579 int shift = style->pixelMetric(QStyle::PM_ButtonMargin, &opt, this) / 2;
580 labelRect.adjust(shift, shift, -shift, -shift);
581 int x, y, w, h;
582 labelRect.getRect(&x, &y, &w, &h);
583
584 if (isChecked() || isDown())
585 {
586 x += style->pixelMetric(QStyle::PM_ButtonShiftHorizontal, &opt, this);
587 y += style->pixelMetric(QStyle::PM_ButtonShiftVertical, &opt, this);
588 }
589
590 QColor fillCol = isEnabled() ? d->color : palette().color(backgroundRole());
591 qDrawShadePanel(&painter, x, y, w, h, palette(), true, 1, 0);
592
593 if (fillCol.isValid())
594 {
595 const QRect rect(x + 1, y + 1, w - 2, h - 2);
596
597 if (fillCol.alpha() < 255)
598 {
599 QPixmap chessboardPattern(16, 16);
600 QPainter patternPainter(&chessboardPattern);
601 patternPainter.fillRect(0, 0, 8, 8, Qt::black);
602 patternPainter.fillRect(8, 8, 8, 8, Qt::black);
603 patternPainter.fillRect(0, 8, 8, 8, Qt::white);
604 patternPainter.fillRect(8, 0, 8, 8, Qt::white);
605 patternPainter.end();
606 painter.fillRect(rect, QBrush(chessboardPattern));
607 }
608
609 painter.fillRect(rect, fillCol);
610 }
611
612 if (hasFocus())
613 {
614 QRect focusRect = style->subElementRect(QStyle::SE_PushButtonFocusRect, &opt, this);
615 QStyleOptionFocusRect focusOpt;
616 focusOpt.initFrom(this);
617 focusOpt.rect = focusRect;
618 focusOpt.backgroundColor = palette().window().color();
619 style->drawPrimitive(QStyle::PE_FrameFocusRect, &focusOpt, &painter, this);
620 }
621}
622
623} // namespace KDcrawIface
const Params2D p
connect(this, SIGNAL(optionsChanged()), this, SLOT(saveOptions()))
RActiveLabel(const QUrl &url=QUrl(), const QString &imgPath=QString(), QWidget *const parent=0)
void updateData(const QUrl &url, const QImage &img)
void setAlignment(Qt::Alignment align)
QSize sizeHint() const override
void setElideMode(Qt::TextElideMode mode)
void resizeEvent(QResizeEvent *) override
RAdjustableLabel(QWidget *const parent=0)
void setAdjustedText(const QString &text=QString())
QSize minimumSizeHint() const override
RColorSelector(QWidget *const parent=0)
void paintEvent(QPaintEvent *) override
void signalColorSelected(const QColor &)
void setColor(const QColor &color)
QFileDialog::Options fdOptions
void setFileDlgMode(QFileDialog::FileMode mode)
RFileSelector(QWidget *const parent=0)
QFileDialog::FileMode fdMode
void signalUrlSelected(const QUrl &)
void setFileDlgTitle(const QString &title)
QLineEdit * lineEdit() const
void setFileDlgFilter(const QString &filter)
void setFileDlgOptions(QFileDialog::Options opts)
void setSpacing(int space)
QSize sizeHint() const override
void setStretchFactor(QWidget *const widget, int stretch)
void setMargin(int margin)
RHBox(QWidget *const parent=0)
void childEvent(QChildEvent *e) override
QSize minimumSizeHint() const override
RLineWidget(Qt::Orientation orientation, QWidget *const parent=0)
RVBox(QWidget *const parent=0)
QVector< QPixmap > m_frames
QPixmap frameAt(int index) const
rgba palette[MAX_PALETTE]
Definition palette.c:35
Simple helpher widgets collection.