Skip to content
RequestInterface.cpp 6.33 KiB
Newer Older
/*
 * Copyright (C) 2017  Kevin Whitaker <eyecreate@gmail.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 */

#include "RequestInterface.h"
#include <Wt/Dbo/Session>
#include <Wt/Dbo/Transaction>
#include "../db/UserAction.h"
#include <Wt/Dbo/ptr>
#include <Wt/Dbo/collection>

RequestInterface::RequestInterface(WebInterface* app)
{
    this->app = app;
    mainLayout = new Wt::WVBoxLayout();
    searchHeader = new Wt::WContainerWidget();
    searchLayout = new Wt::WHBoxLayout();
    searchBox = new Wt::WLineEdit();
    searchBtn = new Wt::WPushButton();
    resultBody = new Wt::WContainerWidget();
    resultLayout = new Wt::WGridLayout();
    
    this->setLayout(mainLayout);
    mainLayout->addWidget(searchHeader,0,Wt::AlignmentFlag::AlignCenter);
    mainLayout->addWidget(resultBody);
    
    searchHeader->setLayout(searchLayout);
    searchBtn->setTextFormat(Wt::XHTMLText);
    searchBtn->decorationStyle().font().setFamily(Wt::WFont::Default,"FontAwesome");
    searchBtn->setText("&#61442;");
    searchBox->enterPressed().connect(this, &RequestInterface::searchClicked);
    searchLayout->addWidget(searchBox);
    searchLayout->addWidget(searchBtn);
    searchBtn->clicked().connect(this, &RequestInterface::searchClicked);
    
    resultBody->setLayout(resultLayout);
    resultBody->setOverflow(Wt::WContainerWidget::OverflowAuto);
    
}

void RequestInterface::trackRequestClicked(AudioTrack track)
{
    if(getRequestCountForUser(app->currentUser) < 3)
    {
        GroovePlayerMgr::getInstance()->requestQueue.push_back(std::pair<AudioTrack,User>(track,app->currentUser));
        //Now check if this is this user's last request and disable buttons.
        updateRequestButtonState();
    }
}

void RequestInterface::trackRemoveClicked(RequestItem* item, AudioTrack track)
{
    bool inVoting = false;
    for(AudioTrack vtrack: GroovePlayerMgr::getInstance()->currentVoteBatch)
    {
        if(vtrack.trackFingerprint == track.trackFingerprint) inVoting = true;
    }
    if(GroovePlayerMgr::getInstance()->currentTrack.trackFingerprint != track.trackFingerprint && !inVoting) 
    {
        Wt::Dbo::Session sqlSession;
        sqlSession.setConnectionPool(*GroovePlayerMgr::getInstance()->connectionPool);
        sqlSession.mapClass<User>("user");
        sqlSession.mapClass<AudioTrack>("tracks");
        sqlSession.mapClass<UserAction>("actions");
        for(std::list<std::pair<AudioTrack,User>>::const_iterator request = GroovePlayerMgr::getInstance()->requestQueue.begin(); request != GroovePlayerMgr::getInstance()->requestQueue.end(); request++)
        {
            if((*request).first.trackFingerprint == track.trackFingerprint) GroovePlayerMgr::getInstance()->requestQueue.erase(request);
        }
        GroovePlayerMgr::getInstance()->removeTrack(&sqlSession,track);
        delete item;
    }
}

void RequestInterface::updateRequestButtonState()
{
    if(getRequestCountForUser(app->currentUser) < 3)
    {
        //enable buttons
        for(RequestItem* item : foundItems)
        {
            if(item != nullptr) item->voteBtn->setEnabled(true);
        }
    }
    else
    {
        //disable buttons
        for(RequestItem* item : foundItems)
        {
            if(item != nullptr) item->voteBtn->setEnabled(false);
        }
    }
}

int RequestInterface::getRequestCountForUser(User user)
{
    int count = 0;
    for(std::pair<AudioTrack,User> request : GroovePlayerMgr::getInstance()->requestQueue)
    {
        if(request.second.username == user.username)
        {
            count += 1;
        }
    }
    return count;

void RequestInterface::searchClicked()
{
    if(!searchBox->text().empty())
    {
        Wt::Dbo::Session sqlSession;
        sqlSession.setConnectionPool(*GroovePlayerMgr::getInstance()->connectionPool);
        sqlSession.mapClass<User>("user");
        sqlSession.mapClass<AudioTrack>("tracks");
        sqlSession.mapClass<UserAction>("actions");
        Wt::Dbo::Transaction searchTransaction(sqlSession);
        
        //Do quick check for invalid seaches
        if(searchBox->text().toUTF8().find("\"") != std::string::npos)
        {
            //Bad character, reject search.
            searchBox->setText("");
            searchTransaction.commit();
            return;
        }
        
        //Do a like search on title, artist, and album on DB
        Wt::Dbo::collection<Wt::Dbo::ptr<AudioTrack>> trackOptions = sqlSession.find<AudioTrack>(std::string("where tracks.name like \"%")+searchBox->text().toUTF8()+std::string("%\" OR tracks.artist like \"%")+searchBox->text().toUTF8()+std::string("%\" OR tracks.album like \"%")+searchBox->text().toUTF8()+std::string("%\"")).limit(30);
        
        //Make sure all items are gone
        for(RequestItem* item: foundItems)
        {
            delete item;
        }
        foundItems.clear();
        resultLayout->clear();
        //Put results into grid
        if(trackOptions.size() > 0 && trackOptions.size() < 50) {
            bool left = true;
            int rowCount = 0;
            for(Wt::Dbo::collection<Wt::Dbo::ptr<AudioTrack>>::const_iterator dbTrack = trackOptions.begin(); dbTrack != trackOptions.end(); ++dbTrack)
            {
                AudioTrack trackItem = (*(*dbTrack));
                GroovePlayerMgr::getInstance()->getPictureFromTrack(&trackItem);
                RequestItem* item = new RequestItem(this,trackItem);
                foundItems.push_back(item);
                resultLayout->addWidget(item,rowCount,left?0:1);
                if(!left) rowCount += 1;
                left = !left;
            }
            searchBox->setText("Not enough results");