aboutsummaryrefslogblamecommitdiff
path: root/src/plugins/General/history/historywindow.cpp
blob: cbba399873ab4b17029bcb2ee521f84ebe39b8d9 (plain) (tree)
1
2
                                                                            
                                                                            







































                                                                             










                                                                                     






                                                                                                

















                                     









                                                                                                                       





















































































































































































































































































































































                                                                                                                                 













                                                                          
/***************************************************************************
 *   Copyright (C) 2017-2019 by Ilya Kotov                                 *
 *   forkotov02@ya.ru                                                      *
 *                                                                         *
 *   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 <QStringList>
#include <QSqlQuery>
#include <QSqlError>
#include <QDateTime>
#include <QSettings>
#include <QProgressBar>
#include <QTreeWidgetItem>
#include <qmmp/qmmp.h>
#include "historywindow.h"
#include "dateinputdialog.h"
#include "progressbaritemdelegate.h"
#include "ui_historywindow.h"

HistoryWindow::HistoryWindow(QSqlDatabase db, QWidget *parent) :
    QWidget(parent),
    m_ui(new Ui::HistoryWindow)
{
    m_ui->setupUi(this);
    setWindowFlags(Qt::Window);
    setAttribute(Qt::WA_DeleteOnClose);
    setAttribute(Qt::WA_QuitOnClose, false);
    m_db = db;

    QDateTime t = QDateTime::currentDateTime();
    t.setTime(QTime(23, 59, 0 ,0));
    m_ui->toDateEdit->setDateTime(t);
    t.setTime(QTime(0, 0, 0, 0));
    t = t.addDays(-7);
    m_ui->fromDateEdit->setDateTime(t);
    m_ui->distributionTreeWidget->setItemDelegate(new ProgressBarItemDelegate(this));
    m_ui->topArtistsTreeWidget->setItemDelegate(new ProgressBarItemDelegate(this));
    m_ui->topSongsTreeWidget->setItemDelegate(new ProgressBarItemDelegate(this));
    m_ui->topGenresTreeWidget->setItemDelegate(new ProgressBarItemDelegate(this));
    m_ui->historyTreeWidget->header()->setSortIndicator(0, Qt::AscendingOrder);
    m_ui->historyTreeWidget->header()->setSortIndicatorShown(true);
    m_ui->historyTreeWidget->header()->setSectionsClickable(true);
    readSettings();
    connect(m_ui->historyTreeWidget->header(), SIGNAL(sortIndicatorChanged(int, Qt::SortOrder)),
            SLOT(onSortIndicatorChanged(int, Qt::SortOrder)));
    m_order = m_ui->historyTreeWidget->header()->sortIndicatorOrder();

    on_executeButton_clicked();
}

HistoryWindow::~HistoryWindow()
{
    delete m_ui;
}

void HistoryWindow::loadHistory()
{
    m_ui->historyTreeWidget->clear();

    if(!m_db.isOpen())
        return;

    QSqlQuery query(m_db);

    if(m_ui->historyTreeWidget->header()->sortIndicatorOrder() == Qt::DescendingOrder)
    {
        query.prepare("SELECT Timestamp,Title,Artist,AlbumArtist,Album,Comment,Genre,Composer,Track,Year,Duration,URL "
                      "FROM track_history WHERE Timestamp BETWEEN :from and :to ORDER BY id DESC");
    }
    else
    {
        query.prepare("SELECT Timestamp,Title,Artist,AlbumArtist,Album,Comment,Genre,Composer,Track,Year,Duration,URL "
                      "FROM track_history WHERE Timestamp BETWEEN :from and :to");
    }
    query.bindValue(":from", m_ui->fromDateEdit->dateTime().toUTC().toString("yyyy-MM-dd hh:mm:ss"));
    query.bindValue(":to", m_ui->toDateEdit->dateTime().toUTC().toString("yyyy-MM-dd hh:mm:ss"));

    if(!query.exec())
    {
        qWarning("HistoryWindow: query error: %s", qPrintable(query.lastError().text()));
        return;
    }

    QColor bgColor = palette().color(QPalette::Highlight);
    QColor textColor = palette().color(QPalette::HighlightedText);

    while (query.next())
    {
        TrackInfo info;
        info.setValue(Qmmp::TITLE,  query.value(1).toString());
        info.setValue(Qmmp::ARTIST,  query.value(2).toString());
        info.setValue(Qmmp::ALBUMARTIST,  query.value(3).toString());
        info.setValue(Qmmp::ALBUM,  query.value(4).toString());
        info.setValue(Qmmp::COMMENT,  query.value(5).toString());
        info.setValue(Qmmp::GENRE,  query.value(6).toString());
        info.setValue(Qmmp::COMPOSER,  query.value(7).toString());
        info.setValue(Qmmp::TRACK,  query.value(8).toString());
        info.setValue(Qmmp::YEAR,  query.value(9).toString());
        info.setDuration(query.value(10).toInt());
        info.setPath(query.value(11).toString());

        QDateTime dateTime = QDateTime::fromString(query.value(0).toString(), "yyyy-MM-dd hh:mm:ss");
        dateTime.setTimeSpec(Qt::UTC);
        QString dateStr = dateTime.toLocalTime().toString(tr("dd MMMM yyyy"));
        QString timeStr = dateTime.toLocalTime().toString(tr("hh:mm:ss"));
        int topLevelCount = m_ui->historyTreeWidget->topLevelItemCount();

        if(!topLevelCount)
        {
            m_ui->historyTreeWidget->addTopLevelItem(new QTreeWidgetItem());
            m_ui->historyTreeWidget->topLevelItem(topLevelCount++)->setText(0, dateStr);
            m_ui->historyTreeWidget->topLevelItem(topLevelCount - 1)->setFirstColumnSpanned(true);
            m_ui->historyTreeWidget->topLevelItem(topLevelCount - 1)->setTextAlignment(0, Qt::AlignCenter);
            m_ui->historyTreeWidget->topLevelItem(topLevelCount - 1)->setBackgroundColor(0, bgColor);
            m_ui->historyTreeWidget->topLevelItem(topLevelCount - 1)->setTextColor(0, textColor);
        }
        else if(m_ui->historyTreeWidget->topLevelItem(topLevelCount - 1)->text(0) != dateStr)
        {
            m_ui->historyTreeWidget->addTopLevelItem(new QTreeWidgetItem());
            m_ui->historyTreeWidget->topLevelItem(topLevelCount++)->setText(0, dateStr);
            m_ui->historyTreeWidget->topLevelItem(topLevelCount - 1)->setFirstColumnSpanned(true);
            m_ui->historyTreeWidget->topLevelItem(topLevelCount - 1)->setTextAlignment(0, Qt::AlignCenter);
            m_ui->historyTreeWidget->topLevelItem(topLevelCount - 1)->setBackgroundColor(0, bgColor);
            m_ui->historyTreeWidget->topLevelItem(topLevelCount - 1)->setTextColor(0, textColor);
        }

        QTreeWidgetItem *topLevelItem = m_ui->historyTreeWidget->topLevelItem(topLevelCount - 1);
        QTreeWidgetItem *item = new QTreeWidgetItem();
        item->setText(0, timeStr);
        item->setText(1, m_formatter.format(info));
        topLevelItem->addChild(item);
    }

    m_ui->historyTreeWidget->expandAll();
}

void HistoryWindow::loadDistribution()
{
    m_ui->distributionTreeWidget->clear();

    if(!m_db.isOpen())
        return;

    QSqlQuery query(m_db);

    query.prepare("SELECT max(c) FROM( SELECT count(*) as c FROM track_history WHERE Timestamp BETWEEN :from and :to "
                  "GROUP BY date(Timestamp, 'localtime'))");
    query.bindValue(":from", m_ui->fromDateEdit->dateTime().toUTC().toString("yyyy-MM-dd hh:mm:ss"));
    query.bindValue(":to", m_ui->toDateEdit->dateTime().toUTC().toString("yyyy-MM-dd hh:mm:ss"));
    if(!query.exec())
    {
        qWarning("HistoryWindow: query error: %s", qPrintable(query.lastError().text()));
        return;
    }
    if(!query.next())
    {
        qWarning("HistoryWindow: empty result");
        return;
    }
    int maxCount = query.value(0).toInt();
    query.finish();

    query.prepare("SELECT count(*), date(Timestamp, 'localtime') FROM track_history WHERE Timestamp BETWEEN :from and :to "
                  "GROUP BY date(Timestamp, 'localtime')");
    query.bindValue(":from", m_ui->fromDateEdit->dateTime().toUTC().toString("yyyy-MM-dd hh:mm:ss"));
    query.bindValue(":to", m_ui->toDateEdit->dateTime().toUTC().toString("yyyy-MM-dd hh:mm:ss"));
    if(!query.exec())
    {
        qWarning("HistoryWindow: query error: %s", qPrintable(query.lastError().text()));
        return;
    }

    QColor bgColor = palette().color(QPalette::Highlight);
    QColor textColor = palette().color(QPalette::HighlightedText);

    while (query.next())
    {
        QDate date = QDate::fromString(query.value(1).toString(), "yyyy-MM-dd");
        QString monthStr = date.toString(tr("MM-yyyy"));
        QString dayStr = date.toString(tr("dd MMMM"));
        int topLevelCount = m_ui->distributionTreeWidget->topLevelItemCount();

        if(!topLevelCount)
        {
            m_ui->distributionTreeWidget->addTopLevelItem(new QTreeWidgetItem());
            m_ui->distributionTreeWidget->topLevelItem(topLevelCount++)->setText(0,  monthStr);
            m_ui->distributionTreeWidget->topLevelItem(topLevelCount - 1)->setFirstColumnSpanned(true);
            m_ui->distributionTreeWidget->topLevelItem(topLevelCount - 1)->setTextAlignment(0, Qt::AlignCenter);
            m_ui->distributionTreeWidget->topLevelItem(topLevelCount - 1)->setBackgroundColor(0, bgColor);
            m_ui->distributionTreeWidget->topLevelItem(topLevelCount - 1)->setTextColor(0, textColor);
        }
        else if(m_ui->distributionTreeWidget->topLevelItem(topLevelCount - 1)->text(0) != monthStr)
        {
            m_ui->distributionTreeWidget->addTopLevelItem(new QTreeWidgetItem());
            m_ui->distributionTreeWidget->topLevelItem(topLevelCount++)->setText(0, monthStr);
            m_ui->distributionTreeWidget->topLevelItem(topLevelCount - 1)->setFirstColumnSpanned(true);
            m_ui->distributionTreeWidget->topLevelItem(topLevelCount - 1)->setTextAlignment(0, Qt::AlignCenter);
            m_ui->distributionTreeWidget->topLevelItem(topLevelCount - 1)->setBackgroundColor(0, bgColor);
            m_ui->distributionTreeWidget->topLevelItem(topLevelCount - 1)->setTextColor(0, textColor);
        }

        QTreeWidgetItem *topLevelItem = m_ui->distributionTreeWidget->topLevelItem(topLevelCount - 1);
        QTreeWidgetItem *item = new QTreeWidgetItem();
        item->setText(0, dayStr);
        topLevelItem->addChild(item);
        item->setData(1, ProgressBarRole, true);
        item->setData(1, ProgressBarMaxRole, maxCount);
        item->setData(1, ProgressBarValueRole, query.value(0).toInt());
    }

    m_ui->distributionTreeWidget->expandAll();
}

void HistoryWindow::loadTopSongs()
{
    m_ui->topSongsTreeWidget->clear();

    if(!m_db.isOpen())
        return;

    QSqlQuery query(m_db);

    query.prepare("SELECT count(*) as c,Timestamp,Title,Artist,AlbumArtist,Album,Comment,Genre,Composer,Track,Year,Duration,URL "
                  "FROM track_history WHERE Timestamp BETWEEN :from and :to "
                  "GROUP BY Artist,Title ORDER BY c DESC LIMIT 100");
    query.bindValue(":from", m_ui->fromDateEdit->dateTime().toUTC().toString("yyyy-MM-dd hh:mm:ss"));
    query.bindValue(":to", m_ui->toDateEdit->dateTime().toUTC().toString("yyyy-MM-dd hh:mm:ss"));

    if(!query.exec())
    {
        qWarning("HistoryWindow: query error: %s", qPrintable(query.lastError().text()));
        return;
    }

    int maxCount = 0;

    while (query.next())
    {
        TrackInfo info;
        info.setValue(Qmmp::TITLE,  query.value(2).toString());
        info.setValue(Qmmp::ARTIST,  query.value(3).toString());
        info.setValue(Qmmp::ALBUMARTIST,  query.value(4).toString());
        info.setValue(Qmmp::ALBUM,  query.value(5).toString());
        info.setValue(Qmmp::COMMENT,  query.value(6).toString());
        info.setValue(Qmmp::GENRE,  query.value(7).toString());
        info.setValue(Qmmp::COMPOSER,  query.value(8).toString());
        info.setValue(Qmmp::TRACK,  query.value(9).toString());
        info.setValue(Qmmp::YEAR,  query.value(10).toString());
        info.setDuration(query.value(11).toInt());
        info.setPath(query.value(12).toString());

        QTreeWidgetItem *item = new QTreeWidgetItem();
        item->setText(0, m_formatter.format(info));

        m_ui->topSongsTreeWidget->addTopLevelItem(item);

        if(!maxCount)
            maxCount = query.value(0).toInt();

        item->setData(1, ProgressBarRole, true);
        item->setData(1, ProgressBarMaxRole, maxCount);
        item->setData(1, ProgressBarValueRole, query.value(0).toInt());
    }
}

void HistoryWindow::loadTopArtists()
{
    m_ui->topArtistsTreeWidget->clear();

    if(!m_db.isOpen())
        return;

    QSqlQuery query(m_db);

    query.prepare("SELECT count(*) as c,Artist "
                  "FROM track_history WHERE (Timestamp BETWEEN :from and :to) AND Artist NOT NULL "
                  "GROUP BY Artist ORDER BY c DESC LIMIT 100");
    query.bindValue(":from", m_ui->fromDateEdit->dateTime().toUTC().toString("yyyy-MM-dd hh:mm:ss"));
    query.bindValue(":to", m_ui->toDateEdit->dateTime().toUTC().toString("yyyy-MM-dd hh:mm:ss"));

    if(!query.exec())
    {
        qWarning("HistoryWindow: query error: %s", qPrintable(query.lastError().text()));
        return;
    }

    int maxCount = 0;

    while (query.next())
    {
        QTreeWidgetItem *item = new QTreeWidgetItem();
        item->setText(0, query.value(1).toString());

        m_ui->topArtistsTreeWidget->addTopLevelItem(item);

        if(!maxCount)
            maxCount = query.value(0).toInt();

        item->setData(1, ProgressBarRole, true);
        item->setData(1, ProgressBarMaxRole, maxCount);
        item->setData(1, ProgressBarValueRole, query.value(0).toInt());
    }
}

void HistoryWindow::loadTopGenres()
{
    m_ui->topGenresTreeWidget->clear();

    if(!m_db.isOpen())
        return;

    QSqlQuery query(m_db);

    query.prepare("SELECT count(*) as c,Genre "
                  "FROM track_history WHERE (Timestamp BETWEEN :from and :to) AND Genre NOT NULL "
                  "GROUP BY Genre ORDER BY c DESC LIMIT 100");
    query.bindValue(":from", m_ui->fromDateEdit->dateTime().toUTC().toString("yyyy-MM-dd hh:mm:ss"));
    query.bindValue(":to", m_ui->toDateEdit->dateTime().toUTC().toString("yyyy-MM-dd hh:mm:ss"));

    if(!query.exec())
    {
        qWarning("HistoryWindow: query error: %s", qPrintable(query.lastError().text()));
        return;
    }

    int maxCount = 0;

    while (query.next())
    {
        QTreeWidgetItem *item = new QTreeWidgetItem();
        item->setText(0, query.value(1).toString());

        m_ui->topGenresTreeWidget->addTopLevelItem(item);

        if(!maxCount)
            maxCount = query.value(0).toInt();

        item->setData(1, ProgressBarRole, true);
        item->setData(1, ProgressBarMaxRole, maxCount);
        item->setData(1, ProgressBarValueRole, query.value(0).toInt());
    }
}

void HistoryWindow::readSettings()
{
    QSettings settings(Qmmp::configFile(), QSettings::IniFormat);
    settings.beginGroup("History");
    restoreGeometry(settings.value("geometry").toByteArray());
    m_ui->historyTreeWidget->header()->restoreState(settings.value("history_state").toByteArray());
    m_ui->distributionTreeWidget->header()->restoreState(settings.value("distribution_state").toByteArray());
    m_ui->topSongsTreeWidget->header()->restoreState(settings.value("top_songs_state").toByteArray());
    m_ui->topArtistsTreeWidget->header()->restoreState(settings.value("top_artists_state").toByteArray());
    m_ui->topGenresTreeWidget->header()->restoreState(settings.value("top_genres_state").toByteArray());
    m_formatter.setPattern(settings.value("title_format", "%if(%p,%p - %t,%t)").toString());
    settings.endGroup();
}

void HistoryWindow::closeEvent(QCloseEvent *)
{
    QSettings settings(Qmmp::configFile(), QSettings::IniFormat);
    settings.beginGroup("History");
    settings.setValue("geometry", saveGeometry());
    settings.setValue("history_state", m_ui->historyTreeWidget->header()->saveState());
    settings.setValue("distribution_state", m_ui->distributionTreeWidget->header()->saveState());
    settings.setValue("top_songs_state", m_ui->topSongsTreeWidget->header()->saveState());
    settings.setValue("top_artists_state", m_ui->topArtistsTreeWidget->header()->saveState());
    settings.setValue("top_genres_state", m_ui->topGenresTreeWidget->header()->saveState());
    settings.endGroup();
}

void HistoryWindow::on_executeButton_clicked()
{
    loadHistory();
    loadDistribution();
    loadTopSongs();
    loadTopArtists();
    loadTopGenres();
}

void HistoryWindow::on_lastWeekButton_clicked()
{
    QDateTime t = QDateTime::currentDateTime();
    t.setTime(QTime(23, 59, 0 ,0));
    m_ui->toDateEdit->setDateTime(t);
    t.setTime(QTime(0, 0, 0, 0));
    t = t.addDays(-t.date().dayOfWeek() + 1);
    m_ui->fromDateEdit->setDateTime(t);
    on_executeButton_clicked();
}

void HistoryWindow::on_lastMonthButton_clicked()
{
    QDateTime t = QDateTime::currentDateTime();
    t.setTime(QTime(23, 59, 0 ,0));
    m_ui->toDateEdit->setDateTime(t);
    t.setTime(QTime(0, 0, 0, 0));
    t.setDate(QDate(t.date().year(), t.date().month(), 1)); ;
    m_ui->fromDateEdit->setDateTime(t);
    on_executeButton_clicked();
}

void HistoryWindow::on_fromButton_clicked()
{
    DateInputDialog d(this);
    d.setSelectedDate(m_ui->fromDateEdit->date());
    if(d.exec() == QDialog::Accepted)
        m_ui->fromDateEdit->setDate(d.selectedDate());
}

void HistoryWindow::on_toButton_clicked()
{
    DateInputDialog d(this);
    d.setSelectedDate(m_ui->toDateEdit->date());
    if(d.exec() == QDialog::Accepted)
        m_ui->toDateEdit->setDate(d.selectedDate());
}

void HistoryWindow::onSortIndicatorChanged(int index, Qt::SortOrder order)
{
    if(index == 0)
    {
        m_order = order;
        loadHistory();
    }
    else //ignore sorting for second section
    {
        //restore sort indicator order
        m_ui->historyTreeWidget->header()->setSortIndicator(0, m_order);
    }
}