#include "displayscreen.h"
#include "ui_displayscreen.h"
#define BLUR_RADIUS 5
DisplayScreen::DisplayScreen(QWidget *parent) :
QWidget(parent),
ui(new Ui::DisplayScreen)
{
ui->setupUi(this);
setPalette(QPalette(QColor(Qt::black),QColor(Qt::black)));
// QPalette p;
// QColor c;
// c.setRgb(123,232,13,50);
// p.setColor(QPalette::Base,c);
// ui->graphicsView->setPalette(p);
// ui->widget->setPalette(QPalette(QColor(Qt::green),QColor(50,50,50,50)));
// ui->widget_2->setPalette(QPalette(QColor(Qt::green),QColor(70,150,250,50)));
timer = new QTimer(this);
timer_out = new QTimer(this);
connect(timer, SIGNAL(timeout()), this, SLOT(fadeIn()));
// connect(timer_out, SIGNAL(timeout()), this, SLOT(fadeOut()));
acounter[0]=255;
btnNext = new ControlButton(QIcon(":/icons/icons/controlNext.png"),
QIcon(":/icons/icons/controlNextHovered.png"),
QIcon(":/icons/icons/controlNextPressed.png"),this);
btnPrev = new ControlButton(QIcon(":/icons/icons/controlPrev.png"),
QIcon(":/icons/icons/controlPrevHovered.png"),
QIcon(":/icons/icons/controlPrevPressed.png"),this);
btnExit = new ControlButton(QIcon(":/icons/icons/controlExit.png"),
QIcon(":/icons/icons/controlExitHovered.png"),
QIcon(":/icons/icons/controlExitPressed.png"),this);
connect(btnNext,SIGNAL(clicked()),this,SLOT(btnNextClicked()));
connect(btnPrev,SIGNAL(clicked()),this,SLOT(btnPrevClicked()));
connect(btnExit,SIGNAL(clicked()),this,SLOT(btnExitClicked()));
}
DisplayScreen::~DisplayScreen()
{
delete ui;
}
void DisplayScreen::keyPressEvent(QKeyEvent *event)
{
// Will get called when a key is pressed
int key = event->key();
if(key == Qt::Key_Left)
prevSlide();
else if(key == Qt::Key_Up)
prevSlide();
else if(key == Qt::Key_P)
prevSlide();
else if(key == Qt::Key_B)
prevSlide();
else if(key == Qt::Key_PageUp)
prevSlide();
else if(key == Qt::Key_Right)
nextSlide();
else if(key == Qt::Key_Down)
nextSlide();
else if(key == Qt::Key_F)
nextSlide();
else if(key == Qt::Key_N)
nextSlide();
else if(key == Qt::Key_PageDown)
nextSlide();
else if(key == Qt::Key_Enter)
nextSlide();
else if(key == Qt::Key_Return)
nextSlide();
else if(key == Qt::Key_Escape)
exitSlide();
else if(key == Qt::Key_X)
exitSlide();
else
QWidget::keyPressEvent(event);
}
void DisplayScreen::setControlsSettings(DisplayControlsSettings &settings)
{
controlsSettings = settings;
positionControlButtons();
}
void DisplayScreen::setControlButtonsVisible(bool visible)
{
btnPrev->setVisible(visible);
btnNext->setVisible(visible);
btnExit->setVisible(visible);
}
void DisplayScreen::positionControlButtons()
{
// set icon sise
int buttonSize(controlsSettings.buttonSize);
if(buttonSize == 0)
buttonSize = 16;
else if(buttonSize == 1)
buttonSize = 24;
else if(buttonSize == 2)
buttonSize = 32;
else if(buttonSize == 3)
buttonSize = 48;
else if(buttonSize == 4)
buttonSize = 64;
else if(buttonSize == 5)
buttonSize = 96;
else
buttonSize = 48;
btnNext->setIconSize(QSize(buttonSize,buttonSize));
btnPrev->setIconSize(QSize(buttonSize,buttonSize));
btnExit->setIconSize(QSize(buttonSize,buttonSize));
// set buttons size to be 2px greater than the icon size
buttonSize +=2;
// calculate button position
int y(this->height()), x(this->width()), margin(5);
// calculate y position
if(controlsSettings.alignmentV==0)//top
y = margin;
else if(controlsSettings.alignmentV==1)//middle
y = (y-buttonSize)/2;
else if(controlsSettings.alignmentV==2)//buttom
y = y-buttonSize-margin;
else
y = y-buttonSize-margin;
// calculate x position
int xt((buttonSize*3)+10); //total width of the button group
if(controlsSettings.alignmentH==0)
x = margin;
else if(controlsSettings.alignmentH==1)
x = (x-xt)/2;
else if (controlsSettings.alignmentH==2)
x = x-xt-margin;
else
x = (x-xt)/2;
int x1(x);
int x2(x1+buttonSize+5);
int x3(x2+buttonSize+5);
//set button positon
btnPrev->setGeometry(x1,y,buttonSize,buttonSize);
btnNext->setGeometry(x2,y,buttonSize,buttonSize);
btnExit->setGeometry(x3,y,buttonSize,buttonSize);
//set button opacity
btnPrev->setOpacity(controlsSettings.opacity);
btnNext->setOpacity(controlsSettings.opacity);
btnExit->setOpacity(controlsSettings.opacity);
// repaint buttons
btnPrev->repaint();
btnNext->repaint();
btnExit->repaint();
}
void DisplayScreen::btnNextClicked()
{
emit nextSlide();
}
void DisplayScreen::btnPrevClicked()
{
emit prevSlide();
}
void DisplayScreen::btnExitClicked()
{
emit exitSlide();
}
void DisplayScreen::fadeIn()
{
if (use_fading)
{
acounter[0]+=64;
if (acounter[0]>255)acounter[0]=255;
if (acounter[0]>254){timer->stop();}
update();
}
}
void DisplayScreen::fadeOut() // For future
{
// acounter[0]-=24;
// if (acounter[0]<0)acounter[0]=0;
// if (acounter[0]<1){timer_out->stop();}
// update();
}
int DisplayScreen::paintTextToRect(QPainter *painter, QRect origrect, int flags, QString text)
{
int left = origrect.left();
int top = origrect.top();
int w = origrect.width();
int h = origrect.height();
QFont font = painter->font();
int orig_font_size = font.pointSize();
// Keep decreasing the font size until the text fits into the allocated space:
QRect rect;
bool exit = false;
while( !exit )
{
rect = painter->boundingRect(left, top, w, h, flags, text);
exit = ( rect.width() <= w && rect.height() <= h );
if( !exit )
{
font.setPointSize( font.pointSize()-1 );
painter->setFont(font);
}
}
// Force wrapping of songs that have really wide lines:
// (Do not allow font to be shrinked less than a 4/5 of the desired font)
if( font.pointSize() < (orig_font_size*4/5) )
{
font.setPointSize(orig_font_size);
painter->setFont(font);
flags = (flags | Qt::TextWordWrap);
//qDebug() << "DRAWING WITH WRAP";
exit = false;
while( !exit )
{
rect = painter->boundingRect(left, top, w, h, flags, text);
exit = ( rect.width() <= w && rect.height() <= h );
if( !exit )
{
font.setPointSize( font.pointSize()-1 );
//qDebug() << "SETTING SIZE:" << font.pointSize();
painter->setFont(font);
}
}
}
painter->drawText(rect, flags, text);
return font.pointSize();
}
void DisplayScreen::renderText(bool text_present)
{
if(use_fading)
{
acounter[0]=0;
// Save the previous image for fade-out effect:
previous_image_pixmap = QPixmap::fromImage(output_image);
}
// For later determening which background to draw, and whether to transition to it:
background_needs_transition = ( use_active_background != text_present );
use_active_background = text_present;
setFont(main_font);
// Render the foreground text:
QImage text_image(width(), height(), QImage::Format_ARGB32);//_Premultiplied);
// Fill transparent background instead of initial garbage (fixes issues on MacOSX):
text_image.fill(qRgba(0, 0, 0, 0)); //transparent background
QPainter text_painter(&text_image);
//text_painter.setRenderHint(QPainter::TextAntialiasing);
//text_painter.setRenderHint( QPainter::Antialiasing);
text_painter.setPen(foreground_color);
text_painter.setFont(font());
// Request SoftProjector to write its text to the QPainter:
emit requestTextDrawing(&text_painter, width(), height());
text_painter.end();
// Draw the shadow image:
QImage shadow_image(width(), height(), QImage::Format_ARGB32);//_Premultiplied);
shadow_image.fill(qRgba(0, 0, 0, 0)); //transparent background
QPainter shadow_painter(&shadow_image);
shadow_painter.setPen(QColor(Qt::black));
shadow_painter.setFont(font());
if(use_shadow)
{
emit requestTextDrawing(&shadow_painter, width(), height());
shadow_painter.end();
}
// Set the blured image to the produced text image:
if(use_blur)
{
/*
Produces a text with a blurred drop shadow using QGraphicsView.
This experiment failed, though, as the quality was a little unsatisfactory.
QPixmap shadow_pixmap = QPixmap::fromImage(text_image);
QGraphicsPixmapItem *shadow_pixmap_item;
shadow_pixmap_item = new QGraphicsPixmapItem(shadow_pixmap);
QGraphicsDropShadowEffect *shadow_effect;
shadow_effect = new QGraphicsDropShadowEffect();
shadow_effect->setColor(QColor(20, 20, 20, 240));//qRgba(0, 0, 0, 90));//Qt::black);
shadow_effect->setOffset(4.0);
shadow_effect->setBlurRadius(10.0);
shadow_pixmap_item->setGraphicsEffect( shadow_effect );
QGraphicsScene scene;
// The scene will take owndership of the item:
scene.addItem(shadow_pixmap_item);
QGraphicsView view(&scene);
view.show();
view.render(&output_painter);
*/
// Blur the shadow:
fastbluralpha(shadow_image, BLUR_RADIUS);
}
QImage temp_image(width(), height(), QImage::Format_ARGB32);//_Premultiplied);
output_image = temp_image;
output_image.fill(qRgba(0, 0, 0, 0)); //transparent background
// Painter for drawing the final image:
QPainter output_painter(&output_image);
//output_painter.setRenderHint(QPainter::TextAntialiasing);
//output_painter.setRenderHint( QPainter::Antialiasing);
// Offset the shadow by a fraction of the font size:
int shadow_offset = ( font().pointSize() / 15 );
// Draw the shadow:
output_painter.drawImage(shadow_offset, shadow_offset, shadow_image);
// Draw the text:
output_painter.drawImage(0, 0, text_image);
output_painter.end();
if(use_fading)
timer->start(33); // 1/24 sec = ~42miliseconds
else
update();
}
void DisplayScreen::setBlur(bool blur)
{
use_blur = blur;
}
void DisplayScreen::setUseShadow(bool useShadow)
{
use_shadow = useShadow;
}
void DisplayScreen::setFading(bool fade)
{
use_fading = fade;
}
void DisplayScreen::setDisplaySettings(DisplaySettings sets)
{
// mySettings = sets;
}
void DisplayScreen::setNewFont(QFont new_font)
{
main_font = new_font;
}
void DisplayScreen::setNewWallpaper(QString path, bool isToUse)
{
if(isToUse)
wallpaper_path = path;
else
wallpaper_path.clear();
if( wallpaper_path.isEmpty() )
wallpaper = QImage();
else
{
wallpaper.load(wallpaper_path);
wallpaper = wallpaper.scaled(width(),height());
}
}
void DisplayScreen::setNewPassiveWallpaper(QString path, bool isToUse)
{
if(isToUse)
passive_wallpaper_path = path;
else
passive_wallpaper_path.clear();
if( passive_wallpaper_path.isEmpty() )
passive_wallpaper = QImage();
else
{
passive_wallpaper.load(passive_wallpaper_path);
passive_wallpaper = passive_wallpaper.scaled(width(), height());
}
}
void DisplayScreen::setForegroundColor(QColor new_color)
{
foreground_color = new_color;
}
void DisplayScreen::paintEvent(QPaintEvent *event )
{
QPainter painter(this);
// This code will, with each iteraction, draw the previous image with increasing transparency, and draw
// the current image with increasing opacity; making a smooth transition:
double curr_opacity = acounter[0] / 255.0;
double prev_opacity = 1.0 - curr_opacity;
// FIXME transition out of the previous background as well
// Draw the background at the current opacity:
if(background_needs_transition)
painter.setOpacity(curr_opacity);
if( use_active_background )
{
// Draw the active wallpaper if there is text to display
if (wallpaper.width()!=width() || wallpaper.isNull())
{
wallpaper.load(wallpaper_path);
if( !wallpaper.isNull() )
wallpaper = wallpaper.scaled(width(),height());
}
if( ! wallpaper.isNull() )
painter.drawImage(0,0,wallpaper);
else
{
// Use black for the background:
painter.setPen(QColor(Qt::black));
painter.drawRect( 0, 0, width(), height() );
}
}
else
{
// Draw the passive wallpaper if set:
//qDebug() << "no text present, passive path:" << passive_wallpaper_path;
if (passive_wallpaper.width()!=width() || passive_wallpaper.isNull())
{
passive_wallpaper.load(passive_wallpaper_path);
if( !passive_wallpaper.isNull() )
passive_wallpaper = passive_wallpaper.scaled(width(),height());
}
if( ! passive_wallpaper.isNull() )
painter.drawImage(0,0, passive_wallpaper);
else
{
// Use black for the background:
painter.setPen(QColor(Qt::black));
painter.drawRect( 0, 0, width(), height() );
}
}
// Draw the previous image into the window, at decreasing opacity:
painter.setOpacity(prev_opacity);
painter.drawPixmap(0, 0, previous_image_pixmap);
// Draw the output_image into the window, at increasing opacity:
painter.setOpacity(curr_opacity);
painter.drawImage(0, 0, output_image);
// Reset the opacity to default opaque:
painter.setOpacity(1.0);
}
// Stack Blur Algorithm by Mario Klingemann <mario@quasimondo.com>
void DisplayScreen::fastbluralpha(QImage &img, int radius)
{
if (radius < 1) {
return;
}
QRgb *pix = (QRgb*)img.bits();
int w = img.width();
int h = img.height();
int wm = w-1;
int hm = h-1;
int wh = w*h;
int div = radius+radius+1;
double junk;
int *r = new int[wh];
int *g = new int[wh];
int *b = new int[wh];
int *a = new int[wh];
int rsum, gsum, bsum, asum, x, y, i, yp, yi, yw;
QRgb p;
int *vmin = new int[qMax(w,h)];
int divsum = (div+1)>>1;
divsum *= divsum;
int *dv = new int[256*divsum];
for (i=0; i < 256*divsum; ++i) {
dv[i] = (i/divsum);
}
yw = yi = 0;
int **stack = new int*[div];
for (int i = 0; i < div; ++i) {
stack[i] = new int[4];
}
int stackpointer;
int stackstart;
int *sir;
int rbs;
int r1 = radius+1;
int routsum, goutsum, boutsum, aoutsum;
int rinsum, ginsum, binsum, ainsum;
for (y = 0; y < h; ++y){
rinsum = ginsum = binsum = ainsum
= routsum = goutsum = boutsum = aoutsum
= rsum = gsum = bsum = asum = 0;
for (i =- radius; i <= radius; ++i) {
p = pix[yi+qMin(wm,qMax(i,0))];
sir = stack[i+radius];
sir[0] = qRed(p);
sir[1] = qGreen(p);
sir[2] = qBlue(p);
sir[3] = qAlpha(p);
rbs = r1-abs(i);
rsum += sir[0]*rbs;
gsum += sir[1]*rbs;
bsum += sir[2]*rbs;
asum += sir[3]*rbs;
if (i > 0){
rinsum += sir[0];
ginsum += sir[1];
binsum += sir[2];
ainsum += sir[3];
} else {
routsum += sir[0];
goutsum += sir[1];
boutsum += sir[2];
aoutsum += sir[3];
}
}
stackpointer = radius;
for (x=0; x < w; ++x) {
r[yi] = dv[rsum];
g[yi] = dv[gsum];
b[yi] = dv[bsum];
a[yi] = dv[asum];
rsum -= routsum;
gsum -= goutsum;
bsum -= boutsum;
asum -= aoutsum;
stackstart = stackpointer-radius+div;
sir = stack[stackstart%div];
routsum -= sir[0];
goutsum -= sir[1];
boutsum -= sir[2];
aoutsum -= sir[3];
if (y == 0) {
vmin[x] = qMin(x+radius+1,wm);
}
p = pix[yw+vmin[x]];
sir[0] = qRed(p);
sir[1] = qGreen(p);
sir[2] = qBlue(p);
sir[3] = qAlpha(p);
rinsum += sir[0];
ginsum += sir[1];
binsum += sir[2];
ainsum += sir[3];
rsum += rinsum;
gsum += ginsum;
bsum += binsum;
asum += ainsum;
stackpointer = (stackpointer+1)%div;
sir = stack[(stackpointer)%div];
routsum += sir[0];
goutsum += sir[1];
boutsum += sir[2];
aoutsum += sir[3];
rinsum -= sir[0];
ginsum -= sir[1];
binsum -= sir[2];
ainsum -= sir[3];
++yi;
}
yw += w;
}
for (x=0; x < w; ++x){
rinsum = ginsum = binsum = ainsum
= routsum = goutsum = boutsum = aoutsum
= rsum = gsum = bsum = asum = 0;
yp =- radius * w;
for (i=-radius; i <= radius; ++i) {
yi=qMax(0,yp)+x;
sir = stack[i+radius];
sir[0] = r[yi];
sir[1] = g[yi];
sir[2] = b[yi];
sir[3] = a[yi];
rbs = r1-abs(i);
rsum += r[yi]*rbs;
gsum += g[yi]*rbs;
bsum += b[yi]*rbs;
asum += a[yi]*rbs;
if (i > 0) {
rinsum += sir[0];
ginsum += sir[1];
binsum += sir[2];
ainsum += sir[3];
} else {
routsum += sir[0];
goutsum += sir[1];
boutsum += sir[2];
aoutsum += sir[3];
}
if (i < hm){
yp += w;
}
}
yi = x;
stackpointer = radius;
for (y=0; y < h; ++y){
junk=dv[asum];
junk=junk*2.4;
if (junk>255)junk=255;
pix[yi] = qRgba(dv[rsum], dv[gsum], dv[bsum], int(junk));///dv[asum]);
rsum -= routsum;
gsum -= goutsum;
bsum -= boutsum;
asum -= aoutsum;
stackstart = stackpointer-radius+div;
sir = stack[stackstart%div];
routsum -= sir[0];
goutsum -= sir[1];
boutsum -= sir[2];
aoutsum -= sir[3];
if (x==0){
vmin[y] = qMin(y+r1,hm)*w;
}
p = x+vmin[y];
sir[0] = r[p];
sir[1] = g[p];
sir[2] = b[p];
sir[3] = a[p];
rinsum += sir[0];
ginsum += sir[1];
binsum += sir[2];
ainsum += sir[3];
rsum += rinsum;
gsum += ginsum;
bsum += binsum;
asum += ainsum;
stackpointer = (stackpointer+1)%div;
sir = stack[stackpointer];
routsum += sir[0];
goutsum += sir[1];
boutsum += sir[2];
aoutsum += sir[3];
rinsum -= sir[0];
ginsum -= sir[1];
binsum -= sir[2];
ainsum -= sir[3];
yi += w;
}
}
delete [] r;
delete [] g;
delete [] b;
delete [] a;
delete [] vmin;
delete [] dv;
}