4
\$\begingroup\$

I've been working on a soundboard software for tabletop games audio immersion in C++ using Qt. The software consists of 2 tabs who provides to a game master a set of individual sounds or scenes to be payed for a particular moment in the game.

The game master can choose the audio to play and the audio is embedded in a resource file from Qt. Besides taking almost 1.5 GB in ram (which have to be wrong), in general the software is running fine, the thing is for the past 2 weeks I feel like I'm not using C++ and Qt the way they are meant to. I'm just pretending to.

I try to come up with C++ 11, 14 and 17 as well as the "Qt way" standards to code (why I'm forced to create so many pointers: the compiler complains when I don't create one...) but it's just not as straightforward as I would like it to be. I want my code to be more elegant, more expressive, more verbose and efficient when running.

If anyone can take the time and point out where my weak spots are in general and what should be my thought process when writing code that would be of great help. If this is not the right place to ask for a code review of like this I'm sure you will point me out on the right direction.

.pro

QT       += core gui multimedia

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

TARGET = SoundBoard
TEMPLATE = app

CONFIG += resources_big

RC_ICONS = Codex_book.ico

DEFINES += QT_DEPRECATED_WARNINGS

SOURCES += \
        main.cpp \
        widget.cpp \
    customlistwidget.cpp \
    customlistwidgetitem.cpp \
    customtabwidget.cpp \
    player.cpp \
    scene.cpp

HEADERS += \
        widget.h \
    customlistwidget.h \
    customlistwidgetitem.h \
    customtabwidget.h \
    player.h \
    scene.h

FORMS += \
        widget.ui \
    player.ui \
    scene.ui \
    player.ui

RESOURCES += \
    src.qrc

Headers:

customlistwidget.h

#ifndef CUSTOMLISTWIDGET_H
#define CUSTOMLISTWIDGET_H

#include <QListWidget>
#include <QVector>

#include "customlistwidgetitem.h"

class CustomListWidget : public QListWidget{
    Q_OBJECT
public:
    CustomListWidget(QWidget *parent = nullptr);

    void addCustomItem(CustomListWidgetItem*);

public slots:
    void setItemPressed(QListWidgetItem*);
    void emitCustomItem(QListWidgetItem*);

signals:
    void customItem(CustomListWidgetItem*);

protected:
    void startDrag(Qt::DropActions supportedActions);

private:
    QVector<CustomListWidgetItem*> list;
    QListWidgetItem *itemToBeSet;
};

#endif // CUSTOMLISTWIDGET_H

customlistwidgetitem.h

#ifndef CUSTOMLISTWIDGETITEM_H
#define CUSTOMLISTWIDGETITEM_H

#include <QListWidgetItem>
#include <QFileInfo>

class CustomListWidgetItem : public QListWidgetItem{
public:
    CustomListWidgetItem(QFileInfo, QIcon, QListWidget *parent = nullptr);
    ~CustomListWidgetItem();

    QFileInfo getFileInfo();

private:
    QFileInfo fileInfo;
};

#endif // CUSTOMLISTWIDGETITEM_H

customtabwidget.h

#ifndef CUSTOMTABWIDGET_H
#define CUSTOMTABWIDGET_H

#include <QTabWidget>
#include <QWidget>

#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QGridLayout>

#include <QScrollArea>

#include <QPushButton>

#include <QVector>

#include <QDragEnterEvent>
#include <QDragLeaveEvent>
#include <QMoveEvent>
#include <QDropEvent>

#include "scene.h"
#include "player.h"
#include "customlistwidgetitem.h"

class CustomTabWidget : public QTabWidget{
    Q_OBJECT

public:
    CustomTabWidget(QWidget *parent = nullptr);

    void setSoundLayout();
    void setSceneLayout();

protected:
    void dragEnterEvent(QDragEnterEvent *event);
    void dragLeaveEvent(QDragLeaveEvent *event);
    void dragMoveEvent(QDragMoveEvent *event);
    void dropEvent(QDropEvent*);

public slots:
    void addScene(bool);
    void stopAllScenes(bool);
    void removeScene(Scene*);
    void removeAllScenes(bool);


    void addSound(bool);
    void stopAllSounds(bool);
    void removeSound(Player*);
    void removeAllSounds(bool);

    void addDefaultSound(CustomListWidgetItem*);

private:
    void appendSound(QStringList &, int);
    void appendScene(QString);

    QVector<Scene*> scenes;
    QVector<Player*> players;

    QGridLayout *soundGrid;
    QGridLayout *sceneGrid;

    QWidget *soundPanel;
    QWidget *scenePanel;

    QHBoxLayout *soundPanelLayout;
    QHBoxLayout *scenePanelLayout;

    QHBoxLayout *hSoundLayout;
    QVBoxLayout *vSoundLayout;

    QHBoxLayout *hSceneLayout;
    QVBoxLayout *vSceneLayout;

    int soundCol;
    int soundRow;

    int sceneCol;
    int sceneRow;

    QPushButton *addSoundButton;
    QPushButton *removeAllSoundsButton;
    QPushButton *stopAllSoundsButton;

    QPushButton *addSceneButton;
    QPushButton *removeAllScenesButton;
    QPushButton *stopAllScenesButton;

    QScrollArea *scrollSound;
    QScrollArea *scrollScene;

    QWidget *soundScroll;
    QWidget *sceneScroll;
};

#endif // CUSTOMTABWIDGET_H

player.h

#ifndef PLAYER_H
#define PLAYER_H

#include <QWidget>
#include <QMediaPlayer>
#include <QMediaPlaylist>
#include <QCheckBox>
#include <QPushButton>

namespace Ui {
    class Player;
}

class Player : public QWidget{
    Q_OBJECT

public:
    explicit Player(QWidget *parent = 0);
    ~Player();

    void setTitle(QString);
    void setIconState(QString);

    QMediaPlaylist *getPlaylist();    
    QMediaPlayer *getPlayer();
    QCheckBox* getLoopButton();
    QPushButton* getPlayStopButton();
    float getSliderValue();

public slots:
    void playStopButton(bool);
    void soundEnd(QMediaPlayer::State);
    void loop(bool);
    void emitThisPlayer(bool);

signals:
    void thisPlayer(Player*);
    void stateChanged(QMediaPlayer::State);
    void sliderValueChanged(int);

private:
    Ui::Player *ui;

    QMediaPlayer *mPlayer;
    QMediaPlaylist *mPlaylist;

    float volume;
};

#endif // PLAYER_H

scene.h

#ifndef SCENE_H
#define SCENE_H

#include <QWidget>
#include <QPushButton>
#include <QGridLayout>

#include <QDragEnterEvent>
#include <QDragLeaveEvent>
#include <QMoveEvent>
#include <QDropEvent>

#include "player.h"
#include "customlistwidget.h"

namespace Ui {
    class Scene;
}

class Scene;

class  Editor : public QWidget{
    Q_OBJECT

public:
    explicit Editor(Scene *parent = 0);
     ~Editor();

    void addDefaultSound(CustomListWidgetItem*);

protected:
    void dragEnterEvent(QDragEnterEvent *event);
    void dragLeaveEvent(QDragLeaveEvent *event);
    void dragMoveEvent(QDragMoveEvent *event);
    void dropEvent(QDropEvent*);

    void resizeEvent(QResizeEvent *evt);
    void closeEvent(QCloseEvent *event);

signals:
    void hidden(bool);

private:
    Scene *scene;
};

class Scene : public QWidget{
    Q_OBJECT

public:
    explicit Scene(QWidget *parent = 0);
    ~Scene();        

    void appendSound(QStringList, int);

    int getCol();
    void setCol(int);

    int getRow();
    void setRow(int);

    void setTitle(QString);
    QPushButton *getPlayStopButton();

public slots:
    void emitThisScene(bool);
    void showEditor(bool);
    void playStop(bool);
    void loopScene(bool);
    void playerStateChanged(QMediaPlayer::State);
    void soundEnd();
    void masterVolume(int);
    void setMasterVolume(int);

    void addSound(bool);
    void stopAllSounds(bool);
    void removeSound(Player *player);
    void removeAllSounds(bool);

signals:
    void thisScene(Scene*);

private:
    void setEditorLayout();    

    Ui::Scene *ui;
    QVector<Player*> players;

    Editor *editor;

    QPushButton *add;
    QPushButton *stopAll;
    QPushButton *removeAll;
    QPushButton *editorPS;

    QGridLayout *grid;
    QWidget *panel;

    QHBoxLayout *h;
    QVBoxLayout *v;

    QHBoxLayout *panelLayout;

    int col;
    int row;

    int stoppedCounter;
};

#endif // SCENE_H

widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>

namespace Ui {
    class Widget;
}

class Widget : public QWidget{
    Q_OBJECT

public:
    explicit Widget(QWidget *parent = 0);
    ~Widget();

private:
    Ui::Widget *ui;
};

#endif // WIDGET_H

Sources:

customlistwidget.cpp

#include "customlistwidget.h"

#include <QMouseEvent>

#include <QMimeData>
#include <QDrag>

#include <QList>
#include <QUrl>

#include <QByteArray>

#include <QDebug>

CustomListWidget::CustomListWidget(QWidget *parent) : QListWidget(parent){

    setMouseTracking(true);

    setDragEnabled(true);
    setDragDropMode(QListWidget::DragOnly);

    connect(this, &CustomListWidget::itemEntered, this, &CustomListWidget::setItemPressed);
    connect(this, &CustomListWidget::itemClicked, this, &CustomListWidget::setItemPressed);
    connect(this, &CustomListWidget::itemDoubleClicked, this, &CustomListWidget::emitCustomItem);
    itemToBeSet = nullptr;

    setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
}

void CustomListWidget::addCustomItem(CustomListWidgetItem *customItem){
    list.push_back(customItem);
    qDebug() << "Custom Item Added: " << list.size() << endl;
    QListWidgetItem *item = new QListWidgetItem(this);
    item->setText(customItem->text());
    item->setIcon(customItem->icon());
}

void CustomListWidget::setItemPressed(QListWidgetItem *item){
    itemToBeSet = item;
    qDebug() << "set" << endl;
}

void CustomListWidget::emitCustomItem(QListWidgetItem *item){
    for(int i = 0; i < list.size(); ++i){
        if(item->text() == list.at(i)->getFileInfo().baseName()){
            emit customItem(list.at(i));
        }
    }
}

void CustomListWidget::startDrag(Qt::DropActions supportedActions){
    (void)supportedActions;
    QList<QUrl> url;

    QByteArray ba;

    QDrag *drag = new QDrag(this);
    QMimeData *mimeData = new QMimeData;

    if(itemToBeSet){
        for(int i = 0; i < list.size(); ++i){
            if(itemToBeSet->text() == list.at(i)->text()){
                ba.append(list.at(i)->getFileInfo().absoluteFilePath());
            }
        }
    }

    mimeData->setData("FileInfo", ba);

    drag->setMimeData(mimeData);
    drag->exec();
}

customlistwidgetitem.cpp

#include "customlistwidgetitem.h"

#include <QDebug>

CustomListWidgetItem::CustomListWidgetItem(QFileInfo infoFile, QIcon icon, QListWidget *parent)
    : QListWidgetItem(parent){

    fileInfo = infoFile;

    setText(infoFile.baseName());
    setIcon(icon);
}

CustomListWidgetItem::~CustomListWidgetItem(){
    delete &fileInfo;
}

QFileInfo CustomListWidgetItem::getFileInfo(){
    return fileInfo;
}

customtabwidget.cpp

#include "customtabwidget.h"

#include "customlistwidget.h"

#include <QMimeData>

#include <QFileDialog>
#include <QInputDialog>

CustomTabWidget::CustomTabWidget(QWidget *parent) : QTabWidget(parent){

    scrollSound = new QScrollArea(this);
    soundScroll = new QWidget(scrollSound);
    soundScroll->setStyleSheet("background-image: url(:/images/Listen.png");

    scrollSound->setWidgetResizable(true);
    soundScroll->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
    setSoundLayout();

    scrollScene = new QScrollArea(this);
    sceneScroll = new QWidget(scrollScene);
    scrollScene->setWidgetResizable(true);
    sceneScroll->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
    setSceneLayout();

    scrollSound->setWidget(soundScroll);
    scrollScene->setWidget(sceneScroll);

    addTab(scrollSound, "Sounds");
    addTab(scrollScene, "Ambience");

    setAcceptDrops(true);

    connect(addSoundButton, &QPushButton::clicked, this, &CustomTabWidget::addSound);
    connect(stopAllSoundsButton, &QPushButton::clicked, this, &CustomTabWidget::stopAllSounds);
    connect(removeAllSoundsButton, &QPushButton::clicked, this, &CustomTabWidget::removeAllSounds);

    connect(addSceneButton, &QPushButton::clicked, this, &CustomTabWidget::addScene);
    connect(stopAllScenesButton, &QPushButton::clicked, this, &CustomTabWidget::stopAllScenes);
    connect(removeAllScenesButton, &QPushButton::clicked, this, &CustomTabWidget::removeAllScenes);
}

void CustomTabWidget::setSoundLayout(){
    CustomListWidget *listWidget = new CustomListWidget;

    QVector<QString> paths = {":/Sounds/Age of Sail/", ":/Sounds/Combat (Future)/", ":/Sounds/Combat (Medieval)/",
                             ":/Sounds/Dark Forest/", ":/Sounds/Death House", ":/Sounds/Deep Six", ":/Sounds/Dungeon",
                             ":/Sounds/Future City", ":/Sounds/House on the Hill", ":/Sounds/Jungle Planet",
                             ":/Sounds/Monster Pack", ":/Sounds/Olde Towne", ":/Sounds/Starship", ":/Sounds/True West",
                             ":Sounds/Wasteland"};

    for(int i = 0; i < paths.size(); ++i){
        QDir dir(paths.at(i));
        QFileInfoList fileList = dir.entryInfoList(QDir::Files, QDir::Name);
        for(int j = 0; j < fileList.size(); ++j){
            listWidget->addCustomItem(new CustomListWidgetItem(fileList.at(j), QIcon(":/icons/music.png")));
            qDebug() << fileList.at(j).absoluteFilePath();
        }
    }

    connect(listWidget, &CustomListWidget::customItem, this, &CustomTabWidget::addDefaultSound);

    soundCol = 0;
    soundRow = 0;

    addSoundButton = new QPushButton;
    stopAllSoundsButton = new QPushButton;
    removeAllSoundsButton = new QPushButton;

    addSoundButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
    addSoundButton->setStyleSheet("background-color: transparent;");
    addSoundButton->setIcon(QIcon(QPixmap(":icons/add.png")));
    addSoundButton->setIconSize(QSize(38, 38));
    addSoundButton->setToolTip("Add Mp3 Track");
    addSoundButton->setToolTipDuration(1000);

    stopAllSoundsButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
    stopAllSoundsButton->setStyleSheet("background-color: transparent;");
    stopAllSoundsButton->setIcon(QIcon(QPixmap(":icons/stopAll.png")));
    stopAllSoundsButton->setIconSize(QSize(38, 38));
    stopAllSoundsButton->setToolTip("Stop All Tracks");
    stopAllSoundsButton->setToolTipDuration(1000);

    removeAllSoundsButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
    removeAllSoundsButton->setStyleSheet("background-color: transparent;");
    removeAllSoundsButton->setIcon(QIcon(QPixmap(":icons/closeAll.png")));
    removeAllSoundsButton->setIconSize(QSize(38, 38));
    removeAllSoundsButton->setToolTip("Remove All Tracks");
    removeAllSoundsButton->setToolTipDuration(1000);

    soundPanel = new QWidget;
    soundPanelLayout = new QHBoxLayout;

    soundGrid = new QGridLayout;

    hSoundLayout = new QHBoxLayout;
    vSoundLayout = new QVBoxLayout;

    soundPanelLayout->addWidget(addSoundButton);
    soundPanelLayout->addWidget(stopAllSoundsButton);
    soundPanelLayout->addWidget(removeAllSoundsButton);
    soundPanelLayout->addStretch(1);

    soundPanel->setLayout(soundPanelLayout);

    hSoundLayout->addLayout(soundGrid);
    hSoundLayout->addStretch(1);

    vSoundLayout->addWidget(soundPanel);
    vSoundLayout->addLayout(hSoundLayout);
    vSoundLayout->addStretch(1);

    QWidget *gridwidget = new QWidget;
    gridwidget->setLayout(vSoundLayout);

    QHBoxLayout *finalLayout = new QHBoxLayout;
    finalLayout->addWidget(listWidget);
    finalLayout->addWidget(gridwidget);

    soundScroll->setLayout(finalLayout);
}

void CustomTabWidget::setSceneLayout(){
    sceneCol = 0;
    sceneRow = 0;

    addSceneButton = new QPushButton;
    stopAllScenesButton = new QPushButton;
    removeAllScenesButton = new QPushButton;

    addSceneButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
    addSceneButton->setStyleSheet("background-color: transparent;");
    addSceneButton->setIcon(QIcon(QPixmap(":icons/scene.png")));
    addSceneButton->setIconSize(QSize(38, 38));
    addSceneButton->setToolTip("Add Mp3 Track");
    addSceneButton->setToolTipDuration(1000);

    stopAllScenesButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
    stopAllScenesButton->setStyleSheet("background-color: transparent;");
    stopAllScenesButton->setIcon(QIcon(QPixmap(":icons/stopAll.png")));
    stopAllScenesButton->setIconSize(QSize(38, 38));
    stopAllScenesButton->setToolTip("Stop All Tracks");
    stopAllScenesButton->setToolTipDuration(1000);

    removeAllScenesButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
    removeAllScenesButton->setStyleSheet("background-color: transparent;");
    removeAllScenesButton->setIcon(QIcon(QPixmap(":icons/closeAll.png")));
    removeAllScenesButton->setIconSize(QSize(38, 38));
    removeAllScenesButton->setToolTip("Remove All Tracks");
    removeAllScenesButton->setToolTipDuration(1000);

    sceneGrid = new QGridLayout;
    scenePanel = new QWidget;
    scenePanelLayout = new QHBoxLayout;
    hSceneLayout = new QHBoxLayout;
    vSceneLayout = new QVBoxLayout;
    sceneScroll->setLayout(vSceneLayout);

    scenePanelLayout->addWidget(addSceneButton);
    scenePanelLayout->addWidget(stopAllScenesButton);
    scenePanelLayout->addWidget(removeAllScenesButton);

    scenePanelLayout->addStretch(1);

    scenePanel->setLayout(scenePanelLayout);

    hSceneLayout->addLayout(sceneGrid);
    hSceneLayout->addStretch(1);

    vSceneLayout->addWidget(scenePanel);
    vSceneLayout->addLayout(hSceneLayout);
    vSceneLayout->addStretch(1);
}

void CustomTabWidget::dragEnterEvent(QDragEnterEvent *event){
    event->acceptProposedAction();
}

void CustomTabWidget::dragLeaveEvent(QDragLeaveEvent *event){
    event->accept();
}

void CustomTabWidget::dragMoveEvent(QDragMoveEvent *event){
    event->acceptProposedAction();
}

void CustomTabWidget::dropEvent(QDropEvent *event){
    QStringList list;
    list.append("qrc" + event->mimeData()->data("FileInfo"));

    if(soundCol < 3){
        appendSound(list, 0);
        ++soundCol;
    } else{
        soundCol = 0;
        soundRow++;
        appendSound(list, 0);
        ++soundCol;
    }
}

void CustomTabWidget::addSound(bool checked){
    (void)checked;

    QFileDialog fileDialog;
    QStringList fileList = fileDialog.getOpenFileNames
            (this, "Open MP3", QDir::currentPath(), "MP3 files (*.mp3)");

    if(!fileList.isEmpty()){
        for(int i = 0; i < fileList.size(); ++i){
            if(soundCol < 3){
                appendSound(fileList, i);
                ++soundCol;
            } else{
                soundCol = 0;
                soundRow++;
                appendSound(fileList, i);
                ++soundCol;
            }
        }
    } else{
        return;
    }
}

void CustomTabWidget::removeSound(Player *player){
    players.removeAll(player);
    player->~Player();

    soundGrid->~QGridLayout();
    soundGrid = new QGridLayout;
    hSoundLayout->insertLayout(hSoundLayout->count() - 1, soundGrid);

    soundRow = 0;
    soundCol = 0;
    int counter = 0;
    while(counter < players.size()){
        if(soundCol < 3){
            soundGrid->addWidget(players.at(counter), soundRow, soundCol);
            ++soundCol;
        } else{
            soundCol = 0;
            ++soundRow;
            soundGrid->addWidget(players.at(counter), soundRow, soundCol);
            ++soundCol;
        }
        ++counter;
    }
}

void CustomTabWidget::removeAllSounds(bool checked){
    (void)checked;
    for(int i = 0; i < players.size(); ++i){
        players.at(i)->~Player();
    }
    players.clear();
    soundCol = 0;
    soundRow = 0;
}

void CustomTabWidget::addDefaultSound(CustomListWidgetItem *item){

    QString path = "qrc" + item->getFileInfo().absoluteFilePath();

    QStringList list;
    list.append(path);

    qDebug() << list << endl;

    if(soundCol < 3){
        appendSound(list, 0);
        ++soundCol;
    } else{
        soundCol = 0;
        soundRow++;
        appendSound(list, 0);
        ++soundCol;
    }
}

void CustomTabWidget::stopAllSounds(bool checked){
    (void)checked;
    for(int i = 0; i < players.size(); ++i){
        players.at(i)->getPlayer()->stop();
    }
}

void CustomTabWidget::addScene(bool checked){
    (void)checked;

    bool ok;
    QString title = QInputDialog::getText(this, "Scene Title",
                                               "Title: ", QLineEdit::Normal,
                                               "", &ok);
    if (ok && !title.isEmpty()){
        if(sceneCol < 5){
            appendScene(title);
            ++sceneCol;
        } else{
            sceneCol = 0;
            ++sceneRow;
            appendScene(title);
            ++sceneCol;
        }
    } else{
        return;
    }
}

void CustomTabWidget::stopAllScenes(bool checked){
    (void)checked;
    for(int i = 0; i < scenes.size(); ++i){
        if(scenes.at(i)->getPlayStopButton()->isChecked()){
            scenes.at(i)->playStop(false);
            scenes.at(i)->getPlayStopButton()->setChecked(false);
//            scenes.at(i)->getPlayStopButton()->click();
        }
    }
}

void CustomTabWidget::removeScene(Scene *scene){
    scenes.removeAll(scene);
    scene->~Scene();

    sceneGrid->~QGridLayout();
    sceneGrid = new QGridLayout;
    hSceneLayout->insertLayout(hSceneLayout->count() - 1, sceneGrid);

    sceneRow = 0;
    sceneCol = 0;
    int counter = 0;
    while(counter < scenes.size()){
        if(sceneCol < 5){
            sceneGrid->addWidget(scenes.at(counter), sceneRow, sceneCol);
            ++sceneCol;
        } else{
            sceneCol = 0;
            ++sceneRow;
            sceneGrid->addWidget(scenes.at(counter), sceneRow, sceneCol);
            ++sceneCol;
        }
        ++counter;
    }
}

void CustomTabWidget::removeAllScenes(bool checked){
    (void)checked;

    for(int i = 0; i < scenes.size(); ++i){
        scenes.at(i)->~Scene();
    }
    scenes.clear();
    sceneCol = 0;
    sceneRow = 0;
}

void CustomTabWidget::appendSound(QStringList &list, int i){
    players.append(new Player(this));
    connect(players.at(players.size() - 1), &Player::thisPlayer, this, &CustomTabWidget::removeSound);
    qDebug() << players.size() << endl;
    players.at(players.size() - 1)->getPlaylist()->addMedia(QUrl(list.at(i)));
    QString file = list.at(i);
    qDebug() << file << endl;
    file.remove(0, file.lastIndexOf('/') + 1);
    file.chop(4);
    players.at(players.size() - 1)->setTitle(file);
    soundGrid->addWidget(players.at(players.size() - 1), soundRow, soundCol);
}

void CustomTabWidget::appendScene(QString title){
    Scene *scene = new Scene;
    connect(scene, &Scene::thisScene, this, &CustomTabWidget::removeScene);
    scenes.append(scene);
    scene->setTitle(title);
    sceneGrid->addWidget(scene, sceneRow, sceneCol);
}

main.cpp

#include "widget.h"
#include <QApplication>

int main(int argc, char *argv[]){
    QApplication a(argc, argv);
    Widget w;
    w.show();

    return a.exec();
}

player.cpp

#include "player.h"
#include "ui_player.h"

#include <QPainter>

Player::Player(QWidget *parent) : QWidget(parent),
    ui(new Ui::Player){
    ui->setupUi(this);

     ui->playStopButton->setCheckable(true);
     ui->playStopButton->setToolTip("Play / Stop");
     ui->playStopButton->setToolTipDuration(500);

     ui->volumeSlider->setValue(50);
     ui->volumeSlider->setToolTip("volume");
     ui->volumeSlider->setToolTipDuration(500);

     ui->deleteButton->setToolTip("Delete");
     ui->deleteButton->setToolTipDuration(500);


     mPlayer = new QMediaPlayer(this);
     mPlaylist = new QMediaPlaylist(this);
     mPlaylist->setPlaybackMode(QMediaPlaylist::CurrentItemOnce);
     mPlayer->setPlaylist(mPlaylist);
     mPlayer->setVolume(ui->volumeSlider->value());

     connect(ui->playStopButton, &QPushButton::clicked, this, &Player::playStopButton);
     connect(ui->deleteButton, &QPushButton::clicked, this, &Player::emitThisPlayer);
     connect(mPlayer, &QMediaPlayer::stateChanged, this, &Player::soundEnd);
     connect(ui->loopCheckBox, &QCheckBox::clicked, this, &Player::loop);
     connect(ui->volumeSlider, &QSlider::valueChanged, mPlayer, &QMediaPlayer::setVolume);
     connect(ui->volumeSlider, &QSlider::valueChanged, this, &Player::sliderValueChanged);

     QFont font;
     font.setBold(true);
     font.setFamily("Arial");
     font.setPointSize(10);
     ui->titleLabel->setFont(font);

//     QColor color = QColor(Qt::white);
//     QPalette palette = ui->titleLabel->palette();
//     palette.setColor(QPalette::WindowText, color);
//     ui->titleLabel->setPalette(palette);

     ui->playStopButton->setStyleSheet("background-color: transparent;");
     setIconState("play");
     ui->playStopButton->setIconSize(QSize(28, 28));

     ui->deleteButton->setStyleSheet("background-color: transparent;");
     ui->deleteButton->setIcon(QIcon(QPixmap(":/icons/minus.png")));
     ui->deleteButton->setIconSize(QSize(28, 28));

     setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
}

Player::~Player(){
    delete ui;
}

void Player::loop(bool checked){
    if(checked){
        mPlaylist->setPlaybackMode(QMediaPlaylist::CurrentItemInLoop);
    } else{
        mPlaylist->setPlaybackMode(QMediaPlaylist::CurrentItemOnce);
    }
}

void Player::soundEnd(QMediaPlayer::State state){
    if(state == QMediaPlayer::State::StoppedState){
        setIconState("play");
        ui->playStopButton->setChecked(false);
    }
}

void Player::playStopButton(bool checked){
    if(checked){
        setIconState("stop");
        mPlayer->play();
    } else{
        setIconState("play");
        if(mPlayer->state() == QMediaPlayer::State::PlayingState){
            mPlayer->stop();
        } else{
            return;
        }
    }
}

void Player::setTitle(QString title){
    ui->titleLabel->setText(title);
}

void Player::setIconState(QString str){
    ui->playStopButton->setIcon(QIcon(QPixmap(":/icons/" +  str  + ".png")));
}

float Player::getSliderValue(){
    return (float)ui->volumeSlider->value();
}

QPushButton* Player::getPlayStopButton(){
    return ui->playStopButton;
}

QCheckBox* Player::getLoopButton(){
    return ui->loopCheckBox;
}

QMediaPlayer *Player::getPlayer(){
    return mPlayer;
}

QMediaPlaylist *Player::getPlaylist(){
    return mPlaylist;
}

void Player::emitThisPlayer(bool checked){
    (void)checked;
    emit thisPlayer(this);
}

scene.cpp

#include "scene.h"
#include "ui_scene.h"

#include <QFileDialog>
#include <QCloseEvent>

#include <QStringList>
#include <QMimeData>

Scene::Scene(QWidget *parent) : QWidget(parent),
    ui(new Ui::Scene){
    ui->setupUi(this);

    stoppedCounter = 0;

    setEditorLayout();

    ui->playStopButton->setCheckable(true);
    ui->playStopButton->setToolTip("Play / Stop");
    ui->playStopButton->setToolTipDuration(500);

    ui->volumeSlider->setToolTip("volume");
    ui->volumeSlider->setToolTipDuration(500);
    ui->volumeSlider->setValue(50);

    ui->deleteButton->setToolTip("Delete Scene");
    ui->deleteButton->setToolTipDuration(500);

    connect(ui->playStopButton, &QPushButton::clicked, this, &Scene::playStop);
    connect(ui->editorButton, &QPushButton::clicked, this, &Scene::showEditor);
    connect(ui->deleteButton, &QPushButton::clicked, this, &Scene::emitThisScene);
    connect(ui->loopCheckBox, &QCheckBox::clicked, this, &Scene::loopScene);
    connect(ui->volumeSlider, &QSlider::valueChanged, this, &Scene::masterVolume);

    connect(add, &QPushButton::clicked, this, &Scene::addSound);
    connect(stopAll, &QPushButton::clicked, this, &Scene::stopAllSounds);
    connect(removeAll, &QPushButton::clicked, this, &Scene::removeAllSounds);
    connect(editorPS, &QPushButton::clicked, this, &Scene::playStop);
//    connect(editor, &Editor::hidden, this, &Scene::playStop);

    QFont font;
    font.setBold(true);
    font.setFamily("Arial");
    font.setPointSize(10);
    ui->titleLabel->setFont(font);

//    QColor color = QColor(Qt::white);
//    QPalette palette = ui->titleLabel->palette();
//    palette.setColor(QPalette::WindowText, color);
//    ui->titleLabel->setPalette(palette);

    ui->playStopButton->setStyleSheet("background-color: transparent;");
    ui->playStopButton->setIcon(QIcon(QPixmap(":/icons/play.png")));
    ui->playStopButton->setIconSize(QSize(28, 28));

    ui->editorButton->setStyleSheet("background-color: transparent;");
    ui->editorButton->setIcon(QIcon(QPixmap(":/icons/settings.png")));
    ui->editorButton->setIconSize(QSize(28, 28));

    ui->deleteButton->setStyleSheet("background-color: transparent;");
    ui->deleteButton->setIcon(QIcon(QPixmap(":/icons/minus.png")));
    ui->deleteButton->setIconSize(QSize(28, 28));

    setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
}

Scene::~Scene(){
    delete ui;
}

void Editor::dragEnterEvent(QDragEnterEvent *event){
    event->acceptProposedAction();
}

void Editor::dragLeaveEvent(QDragLeaveEvent *event){
    event->accept();
}

void Editor::dragMoveEvent(QDragMoveEvent *event){
    event->acceptProposedAction();
}

void Editor::dropEvent(QDropEvent *event){

    QStringList list;
    list.append("qrc" + event->mimeData()->data("FileInfo"));

    if(scene->getCol() < 3){
        scene->appendSound(list, 0);
        scene->setCol(scene->getCol() + 1);
    } else{
        scene->setCol(0);
        scene->setRow(scene->getRow() + 1);
        scene->appendSound(list, 0);
        scene->setCol(scene->getCol() + 1);
    }
}

void Editor::addDefaultSound(CustomListWidgetItem *item){

    QString path = "qrc" + item->getFileInfo().absoluteFilePath();

    QStringList list;
    list.append(path);

    qDebug() << list << endl;

    if(scene->getCol() < 3){
        scene->appendSound(list, 0);
        scene->setCol(scene->getCol() + 1);
    } else{
        scene->setCol(0);
        scene->setRow(scene->getRow() + 1);
        scene->appendSound(list, 0);
        scene->setCol(scene->getCol() + 1);
    }
}

int Scene::getCol(){
    return col;
}

void Scene::setCol(int i){
    col = i;
}

int Scene::getRow(){
    return row;
}

void Scene::setRow(int i){
    row = i;
}

Editor::Editor(Scene *parent) : QWidget(parent){
    scene = parent;
}

void Editor::resizeEvent(QResizeEvent *evt){
    QPixmap bkgnd(":/images/library wizard.jpg");
    bkgnd = bkgnd.scaled(size(), Qt::IgnoreAspectRatio);
    QPalette p = palette(); //copy current, not create new
    p.setBrush(QPalette::Background, bkgnd);
    setPalette(p);

    QWidget::resizeEvent(evt); //call base implementation
}

void Editor::closeEvent(QCloseEvent *event){
    event->ignore();
    scene->stopAllSounds(true);
    this->hide();

//    emit hidden(false);
}

Editor::~Editor(){

}

void Scene::masterVolume(int i){
    for(int j = 0; j < players.size(); ++j){
        players.at(j)->getPlayer()->setVolume((players.at(j)->getSliderValue() / 100) * i);
    }
}

void Scene::setMasterVolume(int i){
    (void)i;
    masterVolume(ui->volumeSlider->value());
}

void Scene::soundEnd(){
    qDebug() << endl << "soundEnd() Emitido";
    if(stoppedCounter == 0){
        qDebug() << "Scene play/stop Button checked false" << endl;
        ui->playStopButton->setIcon(QIcon(QPixmap(":/icons/play.png")));
        ui->playStopButton->setChecked(false);

        editorPS->setIcon(QIcon(QPixmap(":/icons/play.png")));
        editorPS->setChecked(false);
    }
}

void Scene::playerStateChanged(QMediaPlayer::State state){
    qDebug() << endl <<  "Player stateChanged() Emited!";
    if(state == QMediaPlayer::State::PlayingState){
        ++stoppedCounter;
        qDebug() << "Counter ++: " << stoppedCounter << endl;
    } else{
        --stoppedCounter;
        qDebug() << "Counter --: " << stoppedCounter << endl;
    }
    soundEnd();
}

void Scene::loopScene(bool checked){
    for(int i = 0; i < players.size(); ++i){
        players.at(i)->getLoopButton()->setChecked(checked);
        players.at(i)->loop(checked);
    }
}

void Scene::playStop(bool checked){
    if(checked){
        ui->playStopButton->setIcon(QIcon(QPixmap(":/icons/stop.png")));
        ui->playStopButton->setChecked(checked);
        editorPS->setIcon(QIcon(QPixmap(":/icons/stop.png")));
        editorPS->setChecked(checked);

        /* Si hay alguien tocando lo para */
        for(int i = 0; i < players.size(); ++i){
            if(players.at(i)->getPlayer()->state() == QMediaPlayer::PlayingState){
                players.at(i)->playStopButton(false);
                players.at(i)->getPlayStopButton()->setChecked(false);
            }
        }

        /* Los toca todos */
        for(int i = 0; i < players.size(); ++i){
            players.at(i)->playStopButton(checked);
            players.at(i)->getPlayStopButton()->setChecked(checked);
        }
    } else{
        ui->playStopButton->setIcon(QIcon(QPixmap(":/icons/play.png")));
        ui->playStopButton->setChecked(checked);
        editorPS->setIcon(QIcon(QPixmap(":/icons/play.png")));
        editorPS->setChecked(checked);

        /* Si hay alguien tocando lo para */
        for(int i = 0; i < players.size(); ++i){
            if(players.at(i)->getPlayer()->state() == QMediaPlayer::PlayingState){
                players.at(i)->playStopButton(checked);
                players.at(i)->getPlayStopButton()->setChecked(checked);
            }
        }
    }
}

void Scene::removeAllSounds(bool checked){
    (void)checked;

    for(int i = 0; i < players.size(); ++i){        
        players.at(i)->~Player();
    }
    players.clear();
    col = 0;
    row = 0;
    stoppedCounter = 0;
}

void Scene::removeSound(Player *player){
    players.removeAll(player);

    if(player->getPlayer()->PlayingState == QMediaPlayer::PlayingState){
        --stoppedCounter;
    }

    player->~Player();

    grid->~QGridLayout();
    grid = new QGridLayout;
    h->insertLayout(h->count() - 1, grid);

    row = 0;
    col = 0;
    int counter = 0;
    while(counter < players.size()){
        if(col < 3){
            grid->addWidget(players.at(counter), row, col);
            ++col;
        } else{
            col = 0;
            ++row;
            grid->addWidget(players.at(counter), row, col);
            ++col;
        }
        ++counter;
    }    
    soundEnd();
}

void Scene::addSound(bool checked){
    (void)checked;

    QFileDialog fileDialog;
    QStringList fileList = fileDialog.getOpenFileNames
            (this, "Open MP3", QDir::currentPath(), "MP3 files (*.mp3)");

    if(!fileList.isEmpty()){
        for(int i = 0; i < fileList.size(); ++i){
            if(col < 3){
                appendSound(fileList, i);
                ++col;
            } else{
                col = 0;
                row++;
                appendSound(fileList, i);
                ++col;
            }
        }
    } else{
        return;
    }
}

void Scene::stopAllSounds(bool checked){
    (void)checked;
    for(int i = 0; i < players.size(); ++i){
        players.at(i)->getPlayer()->stop();
    }
}

void Scene::setEditorLayout(){
    col = 0;
    row = 0;

    CustomListWidget *listWidget = new CustomListWidget;

    QVector<QString> paths = {":/Sounds/Age of Sail/", ":/Sounds/Combat (Future)/", ":/Sounds/Combat (Medieval)/",
                              ":/Sounds/Dark Forest/", ":/Sounds/Death House", ":/Sounds/Deep Six", ":/Sounds/Dungeon",
                              ":/Sounds/Future City", ":/Sounds/House on the Hill", ":/Sounds/Jungle Planet",
                              ":/Sounds/Monster Pack", ":/Sounds/Olde Towne", ":/Sounds/Starship", ":/Sounds/True West",
                              ":Sounds/Wasteland"};

    for(int i = 0; i < paths.size(); ++i){
        QDir dir(paths.at(i));
        QFileInfoList fileList = dir.entryInfoList(QDir::Files, QDir::Name);
        for(int j = 0; j < fileList.size(); ++j){
            listWidget->addCustomItem(new CustomListWidgetItem(fileList.at(j), QIcon(":/icons/music.png")));
            qDebug() << fileList.at(j).absoluteFilePath();
        }
    }

    editor = new Editor(this);
//    editor->setScene(this);
    editor->setWindowFlags(Qt::Window);
    editor->setWindowModality(Qt::WindowModal);
    editor->setAcceptDrops(true);

    connect(listWidget, &CustomListWidget::customItem, editor, &Editor::addDefaultSound);

    panel = new QWidget;

    add = new QPushButton;
    stopAll = new QPushButton;
    removeAll = new QPushButton;
    editorPS = new QPushButton;
    editorPS->setCheckable(true);

    add->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
    add->setStyleSheet("background-color: transparent;");
    add->setIcon(QIcon(QPixmap(":icons/add.png")));
    add->setIconSize(QSize(38, 38));
    add->setToolTip("Add Mp3 Sound");
    add->setToolTipDuration(500);

    stopAll->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
    stopAll->setStyleSheet("background-color: transparent;");
    stopAll->setIcon(QIcon(QPixmap(":icons/stopAll.png")));
    stopAll->setIconSize(QSize(38, 38));
    stopAll->setToolTip("Stop All Sounds");
    stopAll->setToolTipDuration(500);

    removeAll->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
    removeAll->setStyleSheet("background-color: transparent;");
    removeAll->setIcon(QIcon(QPixmap(":icons/closeAll.png")));
    removeAll->setIconSize(QSize(38, 38));
    removeAll->setToolTip("Remove All Sounds");
    removeAll->setToolTipDuration(500);

    editorPS->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
    editorPS->setStyleSheet("background-color: transparent;");
    editorPS->setIcon(QIcon(QPixmap(":/icons/play.png")));
    editorPS->setIconSize(QSize(28, 28));
    editorPS->setToolTip("Play / Stop All Sounds");
    editorPS->setToolTipDuration(500);

    grid = new QGridLayout;
    panelLayout = new QHBoxLayout;
    h = new QHBoxLayout;
    v = new QVBoxLayout;

    panelLayout->addWidget(add);
    panelLayout->addWidget(stopAll);
    panelLayout->addWidget(removeAll);
    panelLayout->addWidget(editorPS);
    panelLayout->addStretch(1);

    panel->setLayout(panelLayout);

    h->addLayout(grid);
    h->addStretch(1);

    v->addWidget(panel);
    v->addLayout(h);
    v->addStretch(1);

    QWidget *gridwidget = new QWidget;
    gridwidget->setLayout(v);

    QHBoxLayout *finalLayout = new QHBoxLayout;
    finalLayout->addWidget(listWidget);
    finalLayout->addWidget(gridwidget);

    editor->setLayout(finalLayout);
}

void Scene::showEditor(bool checked){
    (void)checked;

    editor->setWindowTitle("Ambience Editor: " + ui->titleLabel->text());
    editor->resize(400, 300);
    editor->show();
}

void Scene::emitThisScene(bool checked){
    (void)checked;
    emit thisScene(this);
}

void Scene::setTitle(QString title){
    ui->titleLabel->setText(title);
}

QPushButton* Scene::getPlayStopButton(){
    return ui->playStopButton;
}

void Scene::appendSound(QStringList list, int i){
    players.append(new Player(this));
    connect(players.at(players.size() - 1), &Player::thisPlayer, this, &Scene::removeSound);
    connect(players.at(players.size() - 1), &Player::sliderValueChanged, this, &Scene::setMasterVolume);

    /* La conexion garantiza que si no hay ningun sonido en loop dentro del editor, el boton
     * de play de la Scene cambie de estado */

    connect(players.at(players.size() - 1)->getPlayer(), &QMediaPlayer::stateChanged,
            this, &Scene::playerStateChanged);

    qDebug() << players.size() << endl;
    players.at(players.size() - 1)->getPlaylist()->addMedia(QUrl(list.at(i)));
    QString file = list.at(i);
    file.remove(0, file.lastIndexOf('/') + 1);
    file.chop(4);
    players.at(players.size() - 1)->setTitle(file);
    grid->addWidget(players.at(players.size() - 1), row, col);
}

widget.cpp

#include "widget.h"
#include "ui_widget.h"

#include "customtabwidget.h"

#include <QHBoxLayout>

#include <QDir>
#include <QFileInfoList>

Widget::Widget(QWidget *parent) : QWidget(parent),
    ui(new Ui::Widget){
    ui->setupUi(this);

    QHBoxLayout *layout = new QHBoxLayout(this);

    CustomTabWidget *tabWidget = new CustomTabWidget;

    layout->addWidget(tabWidget);

    this->setWindowTitle("TableTop SoundBoard v2.0");
    this->resize(800, 600);
}

Widget::~Widget(){
    delete ui;
}
\$\endgroup\$
  • \$\begingroup\$ Have you made sure the high memory usage is your doing and not intrinsic to the framework you're using? \$\endgroup\$ – yuri Apr 7 '18 at 7:18
  • \$\begingroup\$ @yuri How can i make sure its not me, any particular tool or method in mind? As for now my qrc file consists of 603 sounds displayed on a custom list widget. How can this simple thing take more memory than Ubuntu 16.04 running on legacy hardware... \$\endgroup\$ – PVPJCJ Apr 7 '18 at 14:44
  • \$\begingroup\$ A simple approach could be to run an "empty" program consisting only of code responsible for the window/widgets etc. and compare the memory usage to your normal program. You can also try memory profilers such as valgrind/massif. \$\endgroup\$ – yuri Apr 7 '18 at 15:14
  • \$\begingroup\$ @yuri So, tinkering a little bit testing the empty program approach i found this: listWidget->addCustomItem(new CustomListWidgetItem(fileList.at(j), QIcon(":/icons/music.png"))); Why passing the QIcon causes so much overhead? The memory was reduced from 1.5 GB to 40-50 mb. Working right now on Mtuner to find out more. Thx. \$\endgroup\$ – PVPJCJ Apr 9 '18 at 18:33

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.