Added a logo to the project and changed the "settings" button to "menu"
and added some options to the menu that changes the behaviour of the app. such as turning on/off the auto playing of files and the directory and volume control. this is all kept persistent using an IDM formated file in the app's config directory. still having issues with it not calculating the durations properly but i now know why. it's because QMediaPlayer can't calculate the durations of VBR files (variable bit- rate) properly. other than that, everything seems to be working perfectly. i'll add more feasures such as a next/previous file button and a stop button.
|
@ -16,10 +16,21 @@ TEMPLATE = app
|
||||||
SOURCES += main.cpp\
|
SOURCES += main.cpp\
|
||||||
gui/ui.cpp\
|
gui/ui.cpp\
|
||||||
gui/icon.cpp \
|
gui/icon.cpp \
|
||||||
io/aud_file.cpp
|
io/aud_file.cpp \
|
||||||
|
io/conf.cpp \
|
||||||
|
io/idm.cpp \
|
||||||
|
io/int.cpp
|
||||||
|
|
||||||
HEADERS += gui/ui.h\
|
HEADERS += gui/ui.h\
|
||||||
gui/icon.h \
|
gui/icon.h \
|
||||||
io/aud_file.h
|
io/aud_file.h \
|
||||||
|
io/conf.h \
|
||||||
|
io/idm.h \
|
||||||
|
io/int.h
|
||||||
|
|
||||||
RESOURCES += icon_files.qrc
|
RESOURCES += icon_files.qrc
|
||||||
|
|
||||||
|
RC_FILE = logo.rc
|
||||||
|
|
||||||
|
DISTFILES += app_logo.ico \
|
||||||
|
logo.rc
|
||||||
|
|
BIN
app_logo.ico
Normal file
After Width: | Height: | Size: 23 KiB |
54
gui/icon.cpp
|
@ -1,30 +1,50 @@
|
||||||
#include "icon.h"
|
#include "icon.h"
|
||||||
|
|
||||||
Icon::Icon(IconType t, QWidget *parent) : QLabel(parent)
|
Icon::Icon(IconType t, QWidget *parent) : QToolButton(parent)
|
||||||
{
|
{
|
||||||
QRect rect = QApplication::desktop()->screenGeometry();
|
QRect rect = QApplication::desktop()->screenGeometry();
|
||||||
|
|
||||||
setMinimumHeight(rect.height() / 40);
|
setMinimumHeight(rect.height() / 40);
|
||||||
setMinimumWidth(rect.height() / 40);
|
setMinimumWidth(rect.height() / 40);
|
||||||
setCursor(Qt::PointingHandCursor);
|
setCursor(Qt::PointingHandCursor);
|
||||||
|
setToolButtonStyle(Qt::ToolButtonIconOnly);
|
||||||
|
setPopupMode(QToolButton::InstantPopup);
|
||||||
|
|
||||||
switch (t)
|
switch (t)
|
||||||
{
|
{
|
||||||
case PAUSE_PLAY: stateChanged(QMediaPlayer::StoppedState); break;
|
case PAUSE_PLAY:
|
||||||
case SETTINGS: loadImg(":/settings"); break;
|
{
|
||||||
case OPEN: loadImg(":/open"); break;
|
stateChanged(QMediaPlayer::StoppedState);
|
||||||
|
setToolTip(tr("Pause/Play"));
|
||||||
|
|
||||||
|
connect(this, SIGNAL(clicked()), this, SLOT(buttonClicked()));
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case MENU:
|
||||||
|
{
|
||||||
|
loadImg(":/menu");
|
||||||
|
setToolTip(tr("Menu"));
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case OPEN:
|
||||||
|
{
|
||||||
|
loadImg(":/open");
|
||||||
|
setToolTip(tr("Open File"));
|
||||||
|
|
||||||
|
connect(this, SIGNAL(clicked()), this, SLOT(buttonClicked()));
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type = t;
|
type = t;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Icon::mouseReleaseEvent(QMouseEvent *event)
|
void Icon::buttonClicked()
|
||||||
{
|
{
|
||||||
if (event->button() == Qt::LeftButton)
|
if (type == PAUSE_PLAY)
|
||||||
{
|
|
||||||
switch (type)
|
|
||||||
{
|
|
||||||
case PAUSE_PLAY:
|
|
||||||
{
|
{
|
||||||
if (playerState == QMediaPlayer::PlayingState)
|
if (playerState == QMediaPlayer::PlayingState)
|
||||||
{
|
{
|
||||||
|
@ -34,22 +54,10 @@ void Icon::mouseReleaseEvent(QMouseEvent *event)
|
||||||
{
|
{
|
||||||
emit play();
|
emit play();
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
case SETTINGS:
|
else if (type == OPEN)
|
||||||
{
|
|
||||||
emit settings();
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case OPEN:
|
|
||||||
{
|
{
|
||||||
emit open();
|
emit open();
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
11
gui/icon.h
|
@ -2,7 +2,7 @@
|
||||||
#define ICON_H
|
#define ICON_H
|
||||||
|
|
||||||
#include <QWidget>
|
#include <QWidget>
|
||||||
#include <QLabel>
|
#include <QToolButton>
|
||||||
#include <QMediaPlayer>
|
#include <QMediaPlayer>
|
||||||
#include <QMouseEvent>
|
#include <QMouseEvent>
|
||||||
#include <QSvgRenderer>
|
#include <QSvgRenderer>
|
||||||
|
@ -13,7 +13,7 @@
|
||||||
#include <QRect>
|
#include <QRect>
|
||||||
#include <QDesktopWidget>
|
#include <QDesktopWidget>
|
||||||
|
|
||||||
class Icon : public QLabel
|
class Icon : public QToolButton
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
|
@ -22,7 +22,7 @@ public:
|
||||||
enum IconType
|
enum IconType
|
||||||
{
|
{
|
||||||
PAUSE_PLAY,
|
PAUSE_PLAY,
|
||||||
SETTINGS,
|
MENU,
|
||||||
OPEN
|
OPEN
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -38,10 +38,13 @@ private:
|
||||||
QMediaPlayer::State playerState;
|
QMediaPlayer::State playerState;
|
||||||
QString svgFile;
|
QString svgFile;
|
||||||
|
|
||||||
void mouseReleaseEvent(QMouseEvent *event);
|
|
||||||
void paintEvent(QPaintEvent *);
|
void paintEvent(QPaintEvent *);
|
||||||
void loadImg(const QString &path);
|
void loadImg(const QString &path);
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
|
||||||
|
void buttonClicked();
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
|
|
||||||
void pause();
|
void pause();
|
||||||
|
|
98
gui/ui.cpp
|
@ -8,35 +8,34 @@ Ui::Ui(const QStringList &args, QWidget *parent) : QWidget(parent)
|
||||||
|
|
||||||
fileName = new QLabel(this);
|
fileName = new QLabel(this);
|
||||||
slider = new QSlider(this);
|
slider = new QSlider(this);
|
||||||
|
menu = new QMenu(this);
|
||||||
|
trayIcon = new QSystemTrayIcon(QIcon(":/logo"), this);
|
||||||
|
settings = new Icon(Icon::MENU, this);
|
||||||
pausePlay = new Icon(Icon::PAUSE_PLAY, this);
|
pausePlay = new Icon(Icon::PAUSE_PLAY, this);
|
||||||
settings = new Icon(Icon::SETTINGS, this);
|
|
||||||
open = new Icon(Icon::OPEN, this);
|
open = new Icon(Icon::OPEN, this);
|
||||||
player = new QMediaPlayer(this);
|
player = new QMediaPlayer(this);
|
||||||
ioDev = new AudFile(this);
|
ioDev = new AudFile(this);
|
||||||
|
conf = new Conf(this);
|
||||||
pressed = false;
|
pressed = false;
|
||||||
|
|
||||||
QFont fnt = fileName->font();
|
QFont fnt = fileName->font();
|
||||||
QRect rect = QApplication::desktop()->screenGeometry();
|
|
||||||
|
|
||||||
fnt.setBold(true);
|
fnt.setBold(true);
|
||||||
|
|
||||||
setMinimumHeight(rect.height() / 6);
|
|
||||||
setMinimumWidth(rect.width() / 5);
|
|
||||||
setMaximumHeight(rect.height() / 6);
|
|
||||||
setMaximumWidth(rect.width() / 5);
|
|
||||||
setStyleSheet("background-color:white;");
|
setStyleSheet("background-color:white;");
|
||||||
|
|
||||||
fileName->setText(QApplication::applicationName());
|
settings->setMenu(menu);
|
||||||
|
fileName->setText(tr("Ready"));
|
||||||
fileName->setFont(fnt);
|
fileName->setFont(fnt);
|
||||||
slider->setOrientation(Qt::Horizontal);
|
slider->setOrientation(Qt::Horizontal);
|
||||||
slider->setMinimumWidth((rect.width() / 5) - 100);
|
trayIcon->show();
|
||||||
btnLayout->addWidget(pausePlay, 0, Qt::AlignCenter);
|
conf->populateOptionsMenu(menu, this);
|
||||||
btnLayout->addSpacing(rect.height() / 40);
|
player->setVolume(conf->getVolume());
|
||||||
btnLayout->addWidget(open, 0, Qt::AlignCenter);
|
btnLayout->addWidget(pausePlay);
|
||||||
btnLayout->addSpacing(rect.height() / 40);
|
btnLayout->addWidget(open);
|
||||||
btnLayout->addWidget(settings, 0, Qt::AlignCenter);
|
btnLayout->addWidget(settings);
|
||||||
mainLayout->addWidget(fileName, 0, Qt::AlignCenter);
|
mainLayout->addWidget(fileName);
|
||||||
mainLayout->addWidget(slider, 0, Qt::AlignCenter);
|
mainLayout->addWidget(slider);
|
||||||
mainLayout->addWidget(btnWid, 0, Qt::AlignCenter);
|
mainLayout->addWidget(btnWid, 0, Qt::AlignCenter);
|
||||||
|
|
||||||
connect(pausePlay, SIGNAL(pause()), player, SLOT(pause()));
|
connect(pausePlay, SIGNAL(pause()), player, SLOT(pause()));
|
||||||
|
@ -44,10 +43,11 @@ Ui::Ui(const QStringList &args, QWidget *parent) : QWidget(parent)
|
||||||
connect(open, SIGNAL(open()), this, SLOT(openDialog()));
|
connect(open, SIGNAL(open()), this, SLOT(openDialog()));
|
||||||
connect(player, SIGNAL(error(QMediaPlayer::Error)), this, SLOT(error(QMediaPlayer::Error)));
|
connect(player, SIGNAL(error(QMediaPlayer::Error)), this, SLOT(error(QMediaPlayer::Error)));
|
||||||
connect(player, SIGNAL(stateChanged(QMediaPlayer::State)), pausePlay, SLOT(stateChanged(QMediaPlayer::State)));
|
connect(player, SIGNAL(stateChanged(QMediaPlayer::State)), pausePlay, SLOT(stateChanged(QMediaPlayer::State)));
|
||||||
connect(player, SIGNAL(durationChanged(qint64)), this, SLOT(durationChanged(qint64)));
|
|
||||||
connect(player, SIGNAL(positionChanged(qint64)), this, SLOT(posChanged(qint64)));
|
connect(player, SIGNAL(positionChanged(qint64)), this, SLOT(posChanged(qint64)));
|
||||||
|
connect(player, SIGNAL(durationChanged(qint64)), this, SLOT(durChanged(qint64)));
|
||||||
connect(slider, SIGNAL(sliderPressed()), this, SLOT(sliderPressed()));
|
connect(slider, SIGNAL(sliderPressed()), this, SLOT(sliderPressed()));
|
||||||
connect(slider, SIGNAL(sliderReleased()), this, SLOT(sliderReleased()));
|
connect(slider, SIGNAL(sliderReleased()), this, SLOT(sliderReleased()));
|
||||||
|
connect(conf, SIGNAL(volume(int)), player, SLOT(setVolume(int)));
|
||||||
|
|
||||||
if (args.size() > 1)
|
if (args.size() > 1)
|
||||||
{
|
{
|
||||||
|
@ -57,17 +57,30 @@ Ui::Ui(const QStringList &args, QWidget *parent) : QWidget(parent)
|
||||||
|
|
||||||
void Ui::play(const QString &path)
|
void Ui::play(const QString &path)
|
||||||
{
|
{
|
||||||
|
player->blockSignals(true);
|
||||||
|
player->stop();
|
||||||
|
pausePlay->stateChanged(QMediaPlayer::StoppedState);
|
||||||
|
|
||||||
|
if (ioDev->openFile(path))
|
||||||
|
{
|
||||||
QFileInfo info(path);
|
QFileInfo info(path);
|
||||||
|
|
||||||
fileDir = info.path();
|
conf->setLastPath(info.path());
|
||||||
|
|
||||||
slider->setMinimum(0);
|
|
||||||
fileName->setText(info.fileName());
|
fileName->setText(info.fileName());
|
||||||
player->stop();
|
|
||||||
ioDev->close();
|
|
||||||
ioDev->openFile(path);
|
|
||||||
player->setMedia(0, ioDev);
|
player->setMedia(0, ioDev);
|
||||||
|
slider->setValue(0);
|
||||||
|
slider->setMinimum(0);
|
||||||
|
pausePlay->stateChanged(QMediaPlayer::PlayingState);
|
||||||
player->play();
|
player->play();
|
||||||
|
|
||||||
|
adjustSize();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
error(QMediaPlayer::ResourceError);
|
||||||
|
}
|
||||||
|
|
||||||
|
player->blockSignals(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Ui::openDialog()
|
void Ui::openDialog()
|
||||||
|
@ -76,6 +89,7 @@ void Ui::openDialog()
|
||||||
|
|
||||||
fileDialog.setFileMode(QFileDialog::ExistingFile);
|
fileDialog.setFileMode(QFileDialog::ExistingFile);
|
||||||
fileDialog.setNameFilter(tr("Audio Files (*.mp3 *.ogg *.wav *.flac)"));
|
fileDialog.setNameFilter(tr("Audio Files (*.mp3 *.ogg *.wav *.flac)"));
|
||||||
|
fileDialog.setDirectory(conf->getLastPath());
|
||||||
|
|
||||||
if (fileDialog.exec())
|
if (fileDialog.exec())
|
||||||
{
|
{
|
||||||
|
@ -90,18 +104,26 @@ void Ui::error(QMediaPlayer::Error error)
|
||||||
if (error == QMediaPlayer::NoError)
|
if (error == QMediaPlayer::NoError)
|
||||||
{
|
{
|
||||||
box.setText(tr("An unknown error has occured"));
|
box.setText(tr("An unknown error has occured"));
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
box.setText(player->errorString());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (error == QMediaPlayer::FormatError)
|
|
||||||
{
|
|
||||||
box.setIcon(QMessageBox::Warning);
|
box.setIcon(QMessageBox::Warning);
|
||||||
}
|
}
|
||||||
else
|
else if (error == QMediaPlayer::FormatError)
|
||||||
{
|
{
|
||||||
|
box.setText(tr("The format of the media resource isn't fully supported. Playback may still be possible."));
|
||||||
|
box.setIcon(QMessageBox::Warning);
|
||||||
|
}
|
||||||
|
else if (error == QMediaPlayer::AccessDeniedError)
|
||||||
|
{
|
||||||
|
box.setText(tr("The appropriate permissions to play the media resource are not present"));
|
||||||
|
box.setIcon(QMessageBox::Critical);
|
||||||
|
}
|
||||||
|
else if (error == QMediaPlayer::ServiceMissingError)
|
||||||
|
{
|
||||||
|
box.setText(tr("A valid playback service was not found, playback cannot proceed."));
|
||||||
|
box.setIcon(QMessageBox::Critical);
|
||||||
|
}
|
||||||
|
else if (error == QMediaPlayer::ResourceError)
|
||||||
|
{
|
||||||
|
box.setText(tr("Media resource couldn't be resolved."));
|
||||||
box.setIcon(QMessageBox::Critical);
|
box.setIcon(QMessageBox::Critical);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -124,20 +146,20 @@ void Ui::posChanged(qint64 pos)
|
||||||
{
|
{
|
||||||
if (!pressed) slider->setSliderPosition(pos);
|
if (!pressed) slider->setSliderPosition(pos);
|
||||||
|
|
||||||
// if (slider->sliderPosition() == slider->maximum())
|
if ((slider->sliderPosition() == slider->maximum()) && conf->nextFile())
|
||||||
// {
|
{
|
||||||
// QTimer::singleShot(750, this, SLOT(nextFile()));
|
QTimer::singleShot(1000, this, SLOT(nextFile()));
|
||||||
// }
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Ui::durationChanged(qint64 len)
|
void Ui::durChanged(qint64 len)
|
||||||
{
|
{
|
||||||
slider->setMaximum(len);
|
slider->setMaximum(len);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Ui::nextFile()
|
void Ui::nextFile()
|
||||||
{
|
{
|
||||||
QDir dir(fileDir);
|
QDir dir(conf->getLastPath());
|
||||||
|
|
||||||
QStringList filterList;
|
QStringList filterList;
|
||||||
|
|
||||||
|
@ -155,7 +177,7 @@ void Ui::nextFile()
|
||||||
|
|
||||||
if (pos < list.size())
|
if (pos < list.size())
|
||||||
{
|
{
|
||||||
play(fileDir + list[pos]);
|
play(conf->getLastPath() + QDir::separator() + list[pos]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
17
gui/ui.h
|
@ -2,6 +2,7 @@
|
||||||
#define UI_H
|
#define UI_H
|
||||||
|
|
||||||
#include <QWidget>
|
#include <QWidget>
|
||||||
|
#include <QMainWindow>
|
||||||
#include <QVBoxLayout>
|
#include <QVBoxLayout>
|
||||||
#include <QHBoxLayout>
|
#include <QHBoxLayout>
|
||||||
#include <QSlider>
|
#include <QSlider>
|
||||||
|
@ -9,18 +10,20 @@
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
#include <QFile>
|
#include <QFile>
|
||||||
#include <QMediaPlayer>
|
#include <QMediaPlayer>
|
||||||
#include <QUrl>
|
|
||||||
#include <QFileDialog>
|
#include <QFileDialog>
|
||||||
#include <QStringList>
|
#include <QStringList>
|
||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
#include <QFont>
|
#include <QFont>
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
#include <QRect>
|
|
||||||
#include <QDesktopWidget>
|
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
|
#include <QToolButton>
|
||||||
|
#include <QMenu>
|
||||||
|
#include <QSystemTrayIcon>
|
||||||
|
#include <QIcon>
|
||||||
|
|
||||||
#include "icon.h"
|
#include "icon.h"
|
||||||
#include "../io/aud_file.h"
|
#include "../io/aud_file.h"
|
||||||
|
#include "../io/conf.h"
|
||||||
|
|
||||||
class Ui : public QWidget
|
class Ui : public QWidget
|
||||||
{
|
{
|
||||||
|
@ -32,10 +35,12 @@ private:
|
||||||
QSlider *slider;
|
QSlider *slider;
|
||||||
QMediaPlayer *player;
|
QMediaPlayer *player;
|
||||||
AudFile *ioDev;
|
AudFile *ioDev;
|
||||||
|
QToolButton *settings;
|
||||||
|
QSystemTrayIcon *trayIcon;
|
||||||
|
Conf *conf;
|
||||||
|
QMenu *menu;
|
||||||
Icon *pausePlay;
|
Icon *pausePlay;
|
||||||
Icon *settings;
|
|
||||||
Icon *open;
|
Icon *open;
|
||||||
QString fileDir;
|
|
||||||
bool pressed;
|
bool pressed;
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
|
@ -44,7 +49,7 @@ private slots:
|
||||||
void sliderPressed();
|
void sliderPressed();
|
||||||
void sliderReleased();
|
void sliderReleased();
|
||||||
void posChanged(qint64 pos);
|
void posChanged(qint64 pos);
|
||||||
void durationChanged(qint64 len);
|
void durChanged(qint64 len);
|
||||||
void openDialog();
|
void openDialog();
|
||||||
void nextFile();
|
void nextFile();
|
||||||
void play(const QString &path);
|
void play(const QString &path);
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
<RCC>
|
<RCC>
|
||||||
<qresource prefix="/">
|
<qresource prefix="/">
|
||||||
<file alias="play">svg/play-button.svg</file>
|
<file alias="open">svg/open.svg</file>
|
||||||
<file alias="pause">svg/pause.svg</file>
|
<file alias="pause">svg/pause.svg</file>
|
||||||
<file alias="settings">svg/list.svg</file>
|
<file alias="play">svg/play.svg</file>
|
||||||
<file alias="open">svg/eject.svg</file>
|
<file alias="menu">svg/menu.svg</file>
|
||||||
|
<file alias="logo">app_logo.ico</file>
|
||||||
</qresource>
|
</qresource>
|
||||||
</RCC>
|
</RCC>
|
||||||
|
|
|
@ -12,12 +12,16 @@ AudFile::~AudFile()
|
||||||
|
|
||||||
bool AudFile::openFile(const QString &path)
|
bool AudFile::openFile(const QString &path)
|
||||||
{
|
{
|
||||||
|
close();
|
||||||
|
|
||||||
setFileName(path);
|
setFileName(path);
|
||||||
|
|
||||||
bool ret = open(QFile::ReadOnly);
|
bool ret = open(QFile::ReadOnly);
|
||||||
|
|
||||||
if (ret)
|
if (ret)
|
||||||
{
|
{
|
||||||
|
offset = 0;
|
||||||
|
|
||||||
if (peek(3) == "ID3")
|
if (peek(3) == "ID3")
|
||||||
{
|
{
|
||||||
QByteArray header = read(10);
|
QByteArray header = read(10);
|
||||||
|
@ -43,15 +47,20 @@ bool AudFile::openFile(const QString &path)
|
||||||
}
|
}
|
||||||
|
|
||||||
offset += num;
|
offset += num;
|
||||||
|
}
|
||||||
|
|
||||||
seek(0);
|
seek(0);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AudFile::seek(qint64 pos)
|
bool AudFile::seek(qint64 off)
|
||||||
{
|
{
|
||||||
return QFile::seek(pos + offset);
|
return QFile::seek(offset + off);
|
||||||
|
}
|
||||||
|
|
||||||
|
qint64 AudFile::size() const
|
||||||
|
{
|
||||||
|
return QFile::size() - offset;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
#ifndef AUD_FILE_H
|
#ifndef AUD_FILE_H
|
||||||
#define AUD_FILE_H
|
#define AUD_FILE_H
|
||||||
|
|
||||||
|
#include <QBuffer>
|
||||||
#include <QFile>
|
#include <QFile>
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
|
#include <QTimerEvent>
|
||||||
|
|
||||||
class AudFile : public QFile
|
class AudFile : public QFile
|
||||||
{
|
{
|
||||||
|
@ -18,7 +20,8 @@ public:
|
||||||
AudFile(QObject *parent = 0);
|
AudFile(QObject *parent = 0);
|
||||||
|
|
||||||
bool openFile(const QString &path);
|
bool openFile(const QString &path);
|
||||||
bool seek(qint64 pos);
|
bool seek(qint64 off);
|
||||||
|
qint64 size() const;
|
||||||
|
|
||||||
~AudFile();
|
~AudFile();
|
||||||
};
|
};
|
||||||
|
|
150
io/conf.cpp
Normal file
|
@ -0,0 +1,150 @@
|
||||||
|
#include "io/conf.h"
|
||||||
|
|
||||||
|
MenuItem::MenuItem(const QString &label, QWidget *widget, QObject *parent) : QWidgetAction(parent)
|
||||||
|
{
|
||||||
|
str = label;
|
||||||
|
wid = widget;
|
||||||
|
}
|
||||||
|
|
||||||
|
QWidget *MenuItem::createWidget(QWidget *parent)
|
||||||
|
{
|
||||||
|
QWidget *widget = new QWidget(parent);
|
||||||
|
QHBoxLayout *layout = new QHBoxLayout(widget);
|
||||||
|
|
||||||
|
layout->addWidget(new QLabel(str, parent));
|
||||||
|
layout->addStretch();
|
||||||
|
layout->addWidget(wid, 0, Qt::AlignRight);
|
||||||
|
|
||||||
|
return widget;
|
||||||
|
}
|
||||||
|
|
||||||
|
Conf::Conf(QObject *parent) : QObject(parent)
|
||||||
|
{
|
||||||
|
QFile file(confPath(), this);
|
||||||
|
|
||||||
|
QByteArray data;
|
||||||
|
|
||||||
|
if (file.open(QFile::ReadOnly))
|
||||||
|
{
|
||||||
|
data = file.readAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
file.close();
|
||||||
|
|
||||||
|
Idm idm(data, this);
|
||||||
|
|
||||||
|
idm.rdHeader();
|
||||||
|
|
||||||
|
QByteArray pathBa = idm.value(LAST_PATH);
|
||||||
|
QByteArray nextBa = idm.value(NEXT_FILE);
|
||||||
|
QByteArray volBa = idm.value(VOLUME);
|
||||||
|
|
||||||
|
if (!pathBa.isEmpty()) lastPath = pathBa;
|
||||||
|
else lastPath = QDir::homePath();
|
||||||
|
if (!nextBa.isEmpty()) nextFileState = (nextBa == "Y");
|
||||||
|
else nextFileState = true;
|
||||||
|
if (!volBa.isEmpty()) volumeValue = rdInt(volBa);
|
||||||
|
else volumeValue = 50;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Conf::sync()
|
||||||
|
{
|
||||||
|
Idm idm(this);
|
||||||
|
|
||||||
|
idm.wrHeader();
|
||||||
|
idm.insert(LAST_PATH, lastPath.toUtf8());
|
||||||
|
idm.insert(VOLUME, wrInt(volumeValue));
|
||||||
|
|
||||||
|
if (nextFileState) idm.insert(NEXT_FILE, "Y");
|
||||||
|
else idm.insert(NEXT_FILE, "N");
|
||||||
|
|
||||||
|
QFile file(confPath(), this);
|
||||||
|
|
||||||
|
file.open(QFile::WriteOnly | QFile::Truncate);
|
||||||
|
file.write(idm.getBuff());
|
||||||
|
}
|
||||||
|
|
||||||
|
void Conf::populateOptionsMenu(QMenu *menu, QWidget *parent)
|
||||||
|
{
|
||||||
|
QWidget *volWidget = new QWidget(parent);
|
||||||
|
QHBoxLayout *volLayout = new QHBoxLayout(volWidget);
|
||||||
|
QSlider *volSlider = new QSlider(parent);
|
||||||
|
QCheckBox *nextBox = new QCheckBox(parent);
|
||||||
|
|
||||||
|
volSlider->setMinimum(0);
|
||||||
|
volSlider->setMaximum(100);
|
||||||
|
volSlider->setValue(getVolume());
|
||||||
|
volSlider->setOrientation(Qt::Horizontal);
|
||||||
|
volLayout->addWidget(new QLabel("-"));
|
||||||
|
volLayout->addWidget(volSlider);
|
||||||
|
volLayout->addWidget(new QLabel("+"));
|
||||||
|
nextBox->setText("");
|
||||||
|
nextBox->setChecked(nextFile());
|
||||||
|
|
||||||
|
connect(volSlider, SIGNAL(valueChanged(int)), this, SLOT(setVolume(int)));
|
||||||
|
connect(volSlider, SIGNAL(valueChanged(int)), this, SIGNAL(volume(int)));
|
||||||
|
connect(nextBox, SIGNAL(clicked(bool)), this, SLOT(setNextFile(bool)));
|
||||||
|
|
||||||
|
menu->addAction(new MenuItem(tr("Volume"), volWidget, this));
|
||||||
|
menu->addAction(new MenuItem(tr("Auto play next file in directory"), nextBox, this));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Conf::setLastPath(const QString &path)
|
||||||
|
{
|
||||||
|
lastPath = path; sync();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Conf::setNextFile(bool state)
|
||||||
|
{
|
||||||
|
nextFileState = state; sync();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Conf::setVolume(int value)
|
||||||
|
{
|
||||||
|
emit volume(value);
|
||||||
|
|
||||||
|
volumeValue = value; sync();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString Conf::getLastPath()
|
||||||
|
{
|
||||||
|
if (!QDir(lastPath).exists())
|
||||||
|
{
|
||||||
|
lastPath = QDir::homePath();
|
||||||
|
}
|
||||||
|
|
||||||
|
return lastPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Conf::nextFile()
|
||||||
|
{
|
||||||
|
return nextFileState;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Conf::getVolume()
|
||||||
|
{
|
||||||
|
return volumeValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString Conf::confPath()
|
||||||
|
{
|
||||||
|
QString path = QDir::homePath() + '/';
|
||||||
|
|
||||||
|
#ifndef Q_OS_WIN32
|
||||||
|
|
||||||
|
path.append("/.config/");
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
path.append("AppData/Local/");
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
QDir dir;
|
||||||
|
|
||||||
|
path.append(QApplication::applicationName() + '/');
|
||||||
|
|
||||||
|
dir.mkpath(path);
|
||||||
|
|
||||||
|
return path + "conf.idm";
|
||||||
|
}
|
74
io/conf.h
Normal file
|
@ -0,0 +1,74 @@
|
||||||
|
#ifndef CONF_H
|
||||||
|
#define CONF_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <QWidgetAction>
|
||||||
|
#include <QMenu>
|
||||||
|
#include <QSlider>
|
||||||
|
#include <QWidget>
|
||||||
|
#include <QHBoxLayout>
|
||||||
|
#include <QLabel>
|
||||||
|
#include <QCheckBox>
|
||||||
|
#include <QFile>
|
||||||
|
#include <QDir>
|
||||||
|
#include <QApplication>
|
||||||
|
|
||||||
|
#include "idm.h"
|
||||||
|
|
||||||
|
class MenuItem : public QWidgetAction
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
QString str;
|
||||||
|
QWidget *wid;
|
||||||
|
|
||||||
|
QWidget *createWidget(QWidget *parent);
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
MenuItem(const QString &label, QWidget *widget, QObject *parent = 0);
|
||||||
|
};
|
||||||
|
|
||||||
|
class Conf : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
enum DataType
|
||||||
|
{
|
||||||
|
LAST_PATH = 1,
|
||||||
|
NEXT_FILE,
|
||||||
|
VOLUME
|
||||||
|
};
|
||||||
|
|
||||||
|
QString lastPath;
|
||||||
|
bool nextFileState;
|
||||||
|
int volumeValue;
|
||||||
|
|
||||||
|
void sync();
|
||||||
|
QString confPath();
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
|
||||||
|
void setLastPath(const QString &path);
|
||||||
|
void setNextFile(bool state);
|
||||||
|
void setVolume(int value);
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
QString getLastPath();
|
||||||
|
bool nextFile();
|
||||||
|
void populateOptionsMenu(QMenu *menu, QWidget *parent);
|
||||||
|
int getVolume();
|
||||||
|
|
||||||
|
Conf(QObject *parent = 0);
|
||||||
|
|
||||||
|
signals:
|
||||||
|
|
||||||
|
void volume(int);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // CONF_H
|
432
io/idm.cpp
Normal file
|
@ -0,0 +1,432 @@
|
||||||
|
#include "idm.h"
|
||||||
|
|
||||||
|
const QByteArray Idm::TAG = "IDM";
|
||||||
|
const int Idm::MAX_MAJOR = 1;
|
||||||
|
const int Idm::MAX_MINOR = 0;
|
||||||
|
int Idm::DEFAULT_INT_SIZE = 3;
|
||||||
|
int Idm::DEFAULT_FLAGS = 1; // FIXED_KEY_LEN
|
||||||
|
int Idm::DEFAULT_KEY_LEN = 1;
|
||||||
|
int Idm::CURRENT_MAJOR = Idm::MAX_MAJOR;
|
||||||
|
int Idm::CURRENT_MINOR = Idm::MAX_MINOR;
|
||||||
|
|
||||||
|
Idm::Idm(const QByteArray &data, QObject *parent) : QObject(parent)
|
||||||
|
{
|
||||||
|
buffPtr = data;
|
||||||
|
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
|
||||||
|
Idm::Idm(QObject *parent) : QObject(parent)
|
||||||
|
{
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Idm::init()
|
||||||
|
{
|
||||||
|
header = 0;
|
||||||
|
intSize = DEFAULT_INT_SIZE;
|
||||||
|
keyLen = DEFAULT_KEY_LEN;
|
||||||
|
flags = DEFAULT_FLAGS;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Idm::loadData(const QByteArray &data)
|
||||||
|
{
|
||||||
|
op(RELOAD, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
QByteArray &Idm::getBuff()
|
||||||
|
{
|
||||||
|
op(GET_BUFF, QByteArray(), QByteArray(), new QByteArray());
|
||||||
|
|
||||||
|
return buffPtr;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Idm::rdHeader()
|
||||||
|
{
|
||||||
|
return rdExHeader(buffPtr);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Idm::rdExHeader(const QByteArray &data)
|
||||||
|
{
|
||||||
|
bool ret;
|
||||||
|
|
||||||
|
op(RD_HEADER, data, QByteArray(), 0, 0, 0, &ret);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Idm::rdExHeader(const QByteArray &data, int &major, int &minor, int &intSz, int &flgs, int &keyLen)
|
||||||
|
{
|
||||||
|
bool ret = false;
|
||||||
|
|
||||||
|
if (data.startsWith(TAG))
|
||||||
|
{
|
||||||
|
int pos = TAG.size();
|
||||||
|
|
||||||
|
major = rdInt(data.mid(pos++, 1));
|
||||||
|
minor = rdInt(data.mid(pos++, 1));
|
||||||
|
intSz = rdInt(data.mid(pos++, 1));
|
||||||
|
keyLen = rdInt(data.mid(pos++, 1));
|
||||||
|
flgs = rdInt(data.mid(pos, 4));
|
||||||
|
|
||||||
|
if ((major <= MAX_MAJOR) && (minor <= MAX_MINOR))
|
||||||
|
{
|
||||||
|
ret = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Idm::verifyExHeader(const QByteArray &data, int major, int minor)
|
||||||
|
{
|
||||||
|
bool ret = false;
|
||||||
|
|
||||||
|
if (data.startsWith(TAG) && (data.size() == 11))
|
||||||
|
{
|
||||||
|
int pos = TAG.size();
|
||||||
|
int ma = rdInt(data.mid(pos++, 1));
|
||||||
|
int mi = rdInt(data.mid(pos++, 1));
|
||||||
|
|
||||||
|
ret = ((ma <= major) && (mi <= minor));
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
QByteArray Idm::buildHeader(int major, int minor, int intSz, int flgs, int keyLen)
|
||||||
|
{
|
||||||
|
QByteArray ret = TAG;
|
||||||
|
|
||||||
|
ret.append(wrInt(major, 1));
|
||||||
|
ret.append(wrInt(minor, 1));
|
||||||
|
ret.append(wrInt(intSz, 1));
|
||||||
|
ret.append(wrInt(keyLen, 1));
|
||||||
|
ret.append(wrInt(flgs, 4));
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Idm::setKeyLen(int len)
|
||||||
|
{
|
||||||
|
op(SET_KEY_LEN, QByteArray(), QByteArray(), 0, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Idm::setFlags(int flgs)
|
||||||
|
{
|
||||||
|
op(SET_FLAGS, QByteArray(), QByteArray(), 0, flgs);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Idm::wrHeader()
|
||||||
|
{
|
||||||
|
op(WR_HEADER);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Idm::setIntSize(int bytes)
|
||||||
|
{
|
||||||
|
op(SET_INT_SIZE, QByteArray(), QByteArray(), 0, bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Idm::setVersion(int major, int minor)
|
||||||
|
{
|
||||||
|
op(SET_VERSION, QByteArray(), QByteArray(), 0, major, minor);
|
||||||
|
}
|
||||||
|
|
||||||
|
QByteArray Idm::rdData(int addr, int len, bool *ret)
|
||||||
|
{
|
||||||
|
bool ok = false;
|
||||||
|
|
||||||
|
if ((addr < buffPtr.size()) && (addr >= 0))
|
||||||
|
{
|
||||||
|
if ((len + addr) <= buffPtr.size())
|
||||||
|
{
|
||||||
|
ok = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret) *ret = ok;
|
||||||
|
|
||||||
|
if (ok)
|
||||||
|
{
|
||||||
|
return QByteArray::fromRawData(buffPtr.data() + addr, len);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return QByteArray();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Idm::findKey(int &addr, int &dataLen, const QByteArray &key)
|
||||||
|
{
|
||||||
|
bool ok = true;
|
||||||
|
bool found = false;
|
||||||
|
|
||||||
|
while(addr < buffPtr.size() && ok)
|
||||||
|
{
|
||||||
|
int keySize;
|
||||||
|
|
||||||
|
if (flags & FIXED_KEY_LEN)
|
||||||
|
{
|
||||||
|
keySize = keyLen;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
keySize = rdInt(rdData(addr, intSize, &ok));
|
||||||
|
|
||||||
|
addr += intSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ok)
|
||||||
|
{
|
||||||
|
if (key == rdData(addr, keySize, &ok))
|
||||||
|
{
|
||||||
|
found = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
addr += keySize;
|
||||||
|
|
||||||
|
if (ok)
|
||||||
|
{
|
||||||
|
dataLen = rdInt(rdData(addr, intSize, &ok));
|
||||||
|
|
||||||
|
addr += intSize;
|
||||||
|
|
||||||
|
if (found && ok)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
addr += dataLen;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return found;
|
||||||
|
}
|
||||||
|
|
||||||
|
QByteArray Idm::value(const QByteArray &key)
|
||||||
|
{
|
||||||
|
QByteArray ret;
|
||||||
|
|
||||||
|
op(RD_VALUE, key, QByteArray(), &ret);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
QByteArray Idm::value(quint64 key)
|
||||||
|
{
|
||||||
|
int keySize;
|
||||||
|
|
||||||
|
if (flags & FIXED_KEY_LEN) keySize = keyLen;
|
||||||
|
else keySize = intSize;
|
||||||
|
|
||||||
|
return value(wrInt(key, keySize));
|
||||||
|
}
|
||||||
|
|
||||||
|
quint64 Idm::intValue(const QByteArray &key)
|
||||||
|
{
|
||||||
|
return rdInt(value(key));
|
||||||
|
}
|
||||||
|
|
||||||
|
quint64 Idm::intValue(quint64 key)
|
||||||
|
{
|
||||||
|
return rdInt(value(key));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Idm::remove(const QByteArray &key)
|
||||||
|
{
|
||||||
|
bool ret;
|
||||||
|
|
||||||
|
op(RM_VALUE, key, QByteArray(), 0, 0, 0, &ret);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Idm::remove(quint64 key)
|
||||||
|
{
|
||||||
|
int keySize;
|
||||||
|
|
||||||
|
if (flags & FIXED_KEY_LEN) keySize = keyLen;
|
||||||
|
else keySize = intSize;
|
||||||
|
|
||||||
|
return remove(wrInt(key, keySize));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Idm::insert(const QByteArray &key, const QByteArray &data)
|
||||||
|
{
|
||||||
|
bool ret;
|
||||||
|
|
||||||
|
op(WR_VALUE, key, data, 0, 0, 0, &ret);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Idm::insert(quint64 key, quint64 num)
|
||||||
|
{
|
||||||
|
int keySize;
|
||||||
|
|
||||||
|
if (flags & FIXED_KEY_LEN) keySize = keyLen;
|
||||||
|
else keySize = intSize;
|
||||||
|
|
||||||
|
return insert(wrInt(key, keySize), wrInt(num, intSize));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Idm::insert(quint64 key, const QByteArray &data)
|
||||||
|
{
|
||||||
|
int keySize;
|
||||||
|
|
||||||
|
if (flags & FIXED_KEY_LEN) keySize = keyLen;
|
||||||
|
else keySize = intSize;
|
||||||
|
|
||||||
|
return insert(wrInt(key, keySize), data);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Idm::op(Operation opr,
|
||||||
|
const QByteArray &inA,
|
||||||
|
const QByteArray &inB,
|
||||||
|
QByteArray *out,
|
||||||
|
int intA,
|
||||||
|
int intB,
|
||||||
|
bool *ok)
|
||||||
|
{
|
||||||
|
QMutex m;
|
||||||
|
|
||||||
|
m.lock();
|
||||||
|
|
||||||
|
switch(opr)
|
||||||
|
{
|
||||||
|
case SET_KEY_LEN:
|
||||||
|
{
|
||||||
|
keyLen = intA; break;
|
||||||
|
}
|
||||||
|
case SET_FLAGS:
|
||||||
|
{
|
||||||
|
flags = intA; break;
|
||||||
|
}
|
||||||
|
case GET_BUFF:
|
||||||
|
{
|
||||||
|
out = &buffPtr; break;
|
||||||
|
}
|
||||||
|
case RELOAD:
|
||||||
|
{
|
||||||
|
buffPtr = inA; break;
|
||||||
|
}
|
||||||
|
case SET_INT_SIZE:
|
||||||
|
{
|
||||||
|
intSize = intA; break;
|
||||||
|
}
|
||||||
|
case SET_VERSION:
|
||||||
|
{
|
||||||
|
CURRENT_MAJOR = intA;
|
||||||
|
CURRENT_MINOR = intB;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case WR_HEADER:
|
||||||
|
{
|
||||||
|
if (buffPtr.startsWith(TAG))
|
||||||
|
{
|
||||||
|
int pos = TAG.size();
|
||||||
|
|
||||||
|
buffPtr.replace(pos++, 1, wrInt(CURRENT_MAJOR, 1));
|
||||||
|
buffPtr.replace(pos++, 1, wrInt(CURRENT_MINOR, 1));
|
||||||
|
buffPtr.replace(pos++, 1, wrInt(intSize, 1));
|
||||||
|
buffPtr.replace(pos++, 1, wrInt(keyLen, 1));
|
||||||
|
buffPtr.replace(pos++, 4, wrInt(flags, 4));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
buffPtr.insert(0, wrInt(flags, 4));
|
||||||
|
buffPtr.insert(0, wrInt(keyLen, 1));
|
||||||
|
buffPtr.insert(0, wrInt(intSize, 1));
|
||||||
|
buffPtr.insert(0, wrInt(CURRENT_MINOR, 1));
|
||||||
|
buffPtr.insert(0, wrInt(CURRENT_MAJOR, 1));
|
||||||
|
buffPtr.insert(0, TAG);
|
||||||
|
}
|
||||||
|
|
||||||
|
header = 8 + TAG.size();
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case RD_HEADER:
|
||||||
|
{
|
||||||
|
*ok = rdExHeader(inA, CURRENT_MAJOR, CURRENT_MINOR, intSize, flags, keyLen);
|
||||||
|
|
||||||
|
if (*ok) header = 8 + TAG.size();
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case RD_VALUE:
|
||||||
|
{
|
||||||
|
int pos = header;
|
||||||
|
int len = 0;
|
||||||
|
|
||||||
|
if (findKey(pos, len, inA))
|
||||||
|
{
|
||||||
|
out->clear();
|
||||||
|
out->append(buffPtr.mid(pos, len));
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case RM_VALUE:
|
||||||
|
{
|
||||||
|
int pos = header;
|
||||||
|
int len = 0;
|
||||||
|
|
||||||
|
*ok = false;
|
||||||
|
|
||||||
|
if (findKey(pos, len, inA))
|
||||||
|
{
|
||||||
|
if (flags & FIXED_KEY_LEN)
|
||||||
|
{
|
||||||
|
pos -= keyLen + intSize;
|
||||||
|
len += keyLen + intSize;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pos -= inA.size() + (intSize * 2);
|
||||||
|
len += inA.size() + (intSize * 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
buffPtr.remove(pos, len);
|
||||||
|
|
||||||
|
*ok = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case WR_VALUE:
|
||||||
|
{
|
||||||
|
*ok = false;
|
||||||
|
|
||||||
|
remove(inA);
|
||||||
|
|
||||||
|
if (flags & FIXED_KEY_LEN)
|
||||||
|
{
|
||||||
|
if (inA.size() == keyLen)
|
||||||
|
{
|
||||||
|
buffPtr.append(inA + wrInt(inB.size(), intSize) + inB);
|
||||||
|
|
||||||
|
*ok = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!inA.isEmpty())
|
||||||
|
{
|
||||||
|
buffPtr.append(wrInt(inA.size(), intSize) + inA);
|
||||||
|
buffPtr.append(wrInt(inB.size(), intSize) + inB);
|
||||||
|
|
||||||
|
*ok = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m.unlock();
|
||||||
|
}
|
92
io/idm.h
Normal file
|
@ -0,0 +1,92 @@
|
||||||
|
#ifndef IDM_H
|
||||||
|
#define IDM_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <QByteArray>
|
||||||
|
#include <QMutex>
|
||||||
|
|
||||||
|
#include "int.h"
|
||||||
|
|
||||||
|
class Idm : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
enum Flags
|
||||||
|
{
|
||||||
|
FIXED_KEY_LEN = 1
|
||||||
|
};
|
||||||
|
|
||||||
|
static const QByteArray TAG;
|
||||||
|
static const int MAX_MAJOR;
|
||||||
|
static const int MAX_MINOR;
|
||||||
|
static int CURRENT_MAJOR;
|
||||||
|
static int CURRENT_MINOR;
|
||||||
|
static int DEFAULT_INT_SIZE;
|
||||||
|
static int DEFAULT_FLAGS;
|
||||||
|
static int DEFAULT_KEY_LEN;
|
||||||
|
|
||||||
|
static bool verifyExHeader(const QByteArray &data, int major, int minor);
|
||||||
|
static bool rdExHeader(const QByteArray &data, int &major, int &minor, int &intSz, int &flgs, int &keyLen);
|
||||||
|
static QByteArray buildHeader(int major, int minor, int intSz, int flgs, int keyLen);
|
||||||
|
|
||||||
|
explicit Idm(const QByteArray &data, QObject *parent = 0);
|
||||||
|
explicit Idm(QObject *parent = 0);
|
||||||
|
|
||||||
|
void setVersion(int major, int minor);
|
||||||
|
void setFlags(int flgs);
|
||||||
|
void setIntSize(int bytes);
|
||||||
|
void wrHeader();
|
||||||
|
void setKeyLen(int len);
|
||||||
|
void loadData(const QByteArray &data);
|
||||||
|
bool insert(const QByteArray &key, const QByteArray &data);
|
||||||
|
bool insert(quint64 key, quint64 num);
|
||||||
|
bool insert(quint64 key, const QByteArray &data);
|
||||||
|
bool remove(const QByteArray &key);
|
||||||
|
bool remove(quint64 key);
|
||||||
|
bool rdHeader();
|
||||||
|
bool rdExHeader(const QByteArray &data);
|
||||||
|
quint64 intValue(quint64 key);
|
||||||
|
quint64 intValue(const QByteArray &key);
|
||||||
|
QByteArray value(const QByteArray &key);
|
||||||
|
QByteArray value(quint64 key);
|
||||||
|
QByteArray &getBuff();
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
enum Operation
|
||||||
|
{
|
||||||
|
RELOAD,
|
||||||
|
GET_BUFF,
|
||||||
|
RD_HEADER,
|
||||||
|
WR_HEADER,
|
||||||
|
SET_KEY_LEN,
|
||||||
|
SET_FLAGS,
|
||||||
|
SET_INT_SIZE,
|
||||||
|
SET_VERSION,
|
||||||
|
RD_VALUE,
|
||||||
|
WR_VALUE,
|
||||||
|
RM_VALUE
|
||||||
|
};
|
||||||
|
|
||||||
|
QByteArray buffPtr;
|
||||||
|
int header;
|
||||||
|
int intSize;
|
||||||
|
int keyLen;
|
||||||
|
int flags;
|
||||||
|
|
||||||
|
void op(Operation opr,
|
||||||
|
const QByteArray &inA = QByteArray(),
|
||||||
|
const QByteArray &inB = QByteArray(),
|
||||||
|
QByteArray *out = 0,
|
||||||
|
int intA = 0,
|
||||||
|
int intB = 0,
|
||||||
|
bool *ok = 0);
|
||||||
|
|
||||||
|
void init();
|
||||||
|
bool findKey(int &addr, int &dataLen, const QByteArray &key);
|
||||||
|
QByteArray rdData(int, int, bool *ok = 0);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // IDM_H
|
58
io/int.cpp
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
#include "int.h"
|
||||||
|
|
||||||
|
quint64 rdInt(const QByteArray &data)
|
||||||
|
{
|
||||||
|
quint64 out = 0;
|
||||||
|
quint64 outBit = 1;
|
||||||
|
|
||||||
|
for (int i = data.size() - 1; i >= 0; --i)
|
||||||
|
{
|
||||||
|
int byte = data[i];
|
||||||
|
|
||||||
|
for (int inBit = 1; inBit <= 128; inBit *= 2, outBit *= 2)
|
||||||
|
{
|
||||||
|
if ((byte & inBit) != 0) out |= outBit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
float rdFloat(const QByteArray &data)
|
||||||
|
{
|
||||||
|
return data.toFloat();
|
||||||
|
}
|
||||||
|
|
||||||
|
QByteArray wrInt(quint64 value, int intSize)
|
||||||
|
{
|
||||||
|
QByteArray out;
|
||||||
|
quint64 inBit = 1;
|
||||||
|
|
||||||
|
while (value != 0)
|
||||||
|
{
|
||||||
|
int byte = 0;
|
||||||
|
|
||||||
|
for (int outBit = 1; outBit <= 128; outBit *= 2, inBit *= 2)
|
||||||
|
{
|
||||||
|
if (value & inBit)
|
||||||
|
{
|
||||||
|
byte |= outBit;
|
||||||
|
value ^= inBit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
out.insert(0, byte);
|
||||||
|
}
|
||||||
|
|
||||||
|
return out.rightJustified(intSize, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
QByteArray wrInt(quint64 value)
|
||||||
|
{
|
||||||
|
return wrInt(value, INT_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
QByteArray wrFloat(float value)
|
||||||
|
{
|
||||||
|
return QByteArray().setNum(value);
|
||||||
|
}
|
15
io/int.h
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
#ifndef INT_H
|
||||||
|
#define INT_H
|
||||||
|
|
||||||
|
#include <QByteArray>
|
||||||
|
#include <QList>
|
||||||
|
|
||||||
|
#define INT_SIZE 6
|
||||||
|
|
||||||
|
float rdFloat(const QByteArray &data);
|
||||||
|
quint64 rdInt(const QByteArray &data);
|
||||||
|
QByteArray wrInt(quint64 value);
|
||||||
|
QByteArray wrInt(quint64 value, int);
|
||||||
|
QByteArray wrFloat(float value);
|
||||||
|
|
||||||
|
#endif // INT_H
|
|
@ -1,46 +0,0 @@
|
||||||
<?xml version="1.0" encoding="iso-8859-1"?>
|
|
||||||
<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
|
||||||
<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
|
||||||
viewBox="0 0 56.654 56.654" style="enable-background:new 0 0 56.654 56.654;" xml:space="preserve">
|
|
||||||
<g>
|
|
||||||
<path d="M55.043,27.283L31.977,4.306c-0.946-0.942-2.27-1.479-3.66-1.479c-1.389,0-2.714,0.535-3.66,1.478L1.348,27.525
|
|
||||||
C1.29,27.582,1.235,27.64,1.18,27.699c-0.362,0.398-0.641,0.838-0.836,1.297c-0.193,0.459-0.311,0.949-0.338,1.463
|
|
||||||
C0.002,30.537,0,30.613,0,30.69c0,0.021,0,0.037,0,0.06c0.009,0.635,0.155,1.242,0.414,1.791c0.259,0.553,0.638,1.063,1.135,1.504
|
|
||||||
c0.002,0.002,0.004,0.004,0.004,0.004c0.07,0.063,0.144,0.123,0.218,0.182c0.002,0,0.002,0.002,0.004,0.002
|
|
||||||
c0.438,0.344,0.924,0.605,1.434,0.787c0.481,0.172,0.999,0.275,1.538,0.303c0.002,0,0.003,0,0.005,0
|
|
||||||
c0.086,0.002,0.142,0.002,0.262,0.004H51.62c0.006,0,0.01,0,0.015,0c0.007,0,0.015,0,0.019,0c2.762,0,5-2.073,5-4.635
|
|
||||||
C56.654,29.344,56.033,28.131,55.043,27.283z"/>
|
|
||||||
<path d="M56.654,48.161c0,3.129-2.537,5.666-5.668,5.666H5.667C2.537,53.827,0,51.29,0,48.161l0,0c0-3.131,2.537-5.668,5.667-5.668
|
|
||||||
h45.318C54.117,42.493,56.654,45.03,56.654,48.161L56.654,48.161z"/>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
Before Width: | Height: | Size: 1.4 KiB |
46
svg/list.svg
|
@ -1,46 +0,0 @@
|
||||||
<?xml version="1.0" encoding="iso-8859-1"?>
|
|
||||||
<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
|
||||||
<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
|
||||||
viewBox="0 0 62.246 62.246" style="enable-background:new 0 0 62.246 62.246;" xml:space="preserve">
|
|
||||||
<g>
|
|
||||||
<path d="M57.548,45.107H19.965c-2.595,0-4.699,2.105-4.699,4.701c0,2.594,2.104,4.699,4.699,4.699h37.583
|
|
||||||
c2.594,0,4.698-2.105,4.698-4.699C62.246,47.213,60.142,45.107,57.548,45.107z"/>
|
|
||||||
<path d="M57.548,26.402H19.965c-2.595,0-4.699,2.104-4.699,4.7c0,2.595,2.104,4.699,4.699,4.699h37.583
|
|
||||||
c2.594,0,4.698-2.104,4.698-4.699S60.142,26.402,57.548,26.402z"/>
|
|
||||||
<path d="M19.965,17.096h37.583c2.594,0,4.698-2.104,4.698-4.7s-2.104-4.699-4.698-4.699H19.965c-2.595,0-4.699,2.104-4.699,4.699
|
|
||||||
C15.266,14.991,17.37,17.096,19.965,17.096z"/>
|
|
||||||
<circle cx="4.77" cy="12.439" r="4.77"/>
|
|
||||||
<circle cx="4.77" cy="31.102" r="4.769"/>
|
|
||||||
<circle cx="4.77" cy="49.807" r="4.77"/>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
Before Width: | Height: | Size: 1.1 KiB |
12
svg/menu.svg
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
|
||||||
|
<svg version="1.0" xmlns="http://www.w3.org/2000/svg" width="500px" height="500px" viewBox="0 0 5000 5000" preserveAspectRatio="xMidYMid meet">
|
||||||
|
<g id="layer1" fill="#ffffff" stroke="none">
|
||||||
|
<path d="M3880 3027 c-83 -30 -135 -63 -197 -126 -94 -95 -143 -219 -143 -361 0 -179 78 -329 225 -430 155 -107 390 -108 544 -4 151 102 231 252 231 434 0 50 -7 109 -16 141 -50 170 -182 306 -343 353 -83 24 -221 21 -301 -7z"/>
|
||||||
|
<path d="M850 3017 c-160 -57 -275 -180 -324 -346 -21 -71 -21 -211 0 -282 35 -119 107 -219 209 -289 155 -107 390 -108 544 -4 151 102 231 252 231 434 0 50 -7 109 -16 141 -50 170 -182 306 -343 353 -83 24 -221 21 -301 -7z"/>
|
||||||
|
<path d="M2360 3017 c-83 -30 -135 -63 -197 -126 -94 -95 -143 -219 -143 -361 0 -179 78 -329 225 -430 155 -107 390 -108 544 -4 151 102 231 252 231 434 0 50 -7 109 -16 141 -50 170 -182 306 -343 353 -83 24 -221 21 -301 -7z"/>
|
||||||
|
</g>
|
||||||
|
<g id="layer2" fill="#b6748b" stroke="none">
|
||||||
|
<path d="M0 2500 l0 -2500 2500 0 2500 0 0 2500 0 2500 -2500 0 -2500 0 0 -2500z m4181 534 c161 -47 293 -183 343 -353 9 -32 16 -91 16 -141 0 -182 -80 -332 -231 -434 -154 -104 -389 -103 -544 4 -147 101 -225 251 -225 430 0 289 214 509 496 510 54 0 112 -6 145 -16z m-3030 -10 c161 -47 293 -183 343 -353 9 -32 16 -91 16 -141 0 -182 -80 -332 -231 -434 -154 -104 -389 -103 -544 4 -147 101 -225 251 -225 430 0 289 214 509 496 510 54 0 112 -6 145 -16z m1510 0 c161 -47 293 -183 343 -353 9 -32 16 -91 16 -141 0 -182 -80 -332 -231 -434 -154 -104 -389 -103 -544 4 -147 101 -225 251 -225 430 0 289 214 509 496 510 54 0 112 -6 145 -16z"/>
|
||||||
|
</g>
|
||||||
|
|
||||||
|
</svg>
|
After Width: | Height: | Size: 1.6 KiB |
10
svg/open.svg
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
|
||||||
|
<svg version="1.0" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 5010 5000" preserveAspectRatio="xMidYMid meet">
|
||||||
|
<g id="layer1" fill="#ffffff" stroke="none">
|
||||||
|
<path d="M770 2490 l0 -1200 895 0 895 0 0 160 0 160 825 0 825 0 0 1040 0 1040 -1720 0 -1720 0 0 -1200z"/>
|
||||||
|
</g>
|
||||||
|
<g id="layer2" fill="#10715B" stroke="none">
|
||||||
|
<path d="M0 2500 l0 -2500 2505 0 2505 0 0 2500 0 2500 -2505 0 -2505 0 0 -2500z m4210 150 l0 -1040 -825 0 -825 0 0 -160 0 -160 -895 0 -895 0 0 1200 0 1200 1720 0 1720 0 0 -1040z"/>
|
||||||
|
</g>
|
||||||
|
|
||||||
|
</svg>
|
After Width: | Height: | Size: 624 B |
|
@ -1,41 +1,11 @@
|
||||||
<?xml version="1.0" encoding="iso-8859-1"?>
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
|
||||||
<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
<svg version="1.0" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 5010 5000" preserveAspectRatio="xMidYMid meet">
|
||||||
<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
<g id="layer1" fill="#ffffff" stroke="none">
|
||||||
viewBox="0 0 47.607 47.607" style="enable-background:new 0 0 47.607 47.607;" xml:space="preserve">
|
<path d="M1220 2575 l0 -1925 385 0 385 0 0 1925 0 1925 -385 0 -385 0 0 -1925z"/>
|
||||||
<g>
|
<path d="M2870 2575 l0 -1925 385 0 385 0 0 1925 0 1925 -385 0 -385 0 0 -1925z"/>
|
||||||
<path d="M17.991,40.976c0,3.662-2.969,6.631-6.631,6.631l0,0c-3.662,0-6.631-2.969-6.631-6.631V6.631C4.729,2.969,7.698,0,11.36,0
|
</g>
|
||||||
l0,0c3.662,0,6.631,2.969,6.631,6.631V40.976z"/>
|
<g id="layer2" fill="#1134c1" stroke="none">
|
||||||
<path d="M42.877,40.976c0,3.662-2.969,6.631-6.631,6.631l0,0c-3.662,0-6.631-2.969-6.631-6.631V6.631
|
<path d="M0 2500 l0 -2500 2505 0 2505 0 0 2500 0 2500 -2505 0 -2505 0 0 -2500z m1990 75 l0 -1925 -385 0 -385 0 0 1925 0 1925 385 0 385 0 0 -1925z m1650 0 l0 -1925 -385 0 -385 0 0 1925 0 1925 385 0 385 0 0 -1925z"/>
|
||||||
C29.616,2.969,32.585,0,36.246,0l0,0c3.662,0,6.631,2.969,6.631,6.631V40.976z"/>
|
</g>
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
</g>
|
|
||||||
</svg>
|
</svg>
|
Before Width: | Height: | Size: 875 B After Width: | Height: | Size: 716 B |
|
@ -1,40 +0,0 @@
|
||||||
<?xml version="1.0" encoding="iso-8859-1"?>
|
|
||||||
<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
|
||||||
<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
|
||||||
viewBox="0 0 47.604 47.604" style="enable-background:new 0 0 47.604 47.604;" xml:space="preserve">
|
|
||||||
<g>
|
|
||||||
<path d="M43.331,21.237L7.233,0.397c-0.917-0.529-2.044-0.529-2.96,0c-0.916,0.528-1.48,1.505-1.48,2.563v41.684
|
|
||||||
c0,1.058,0.564,2.035,1.48,2.563c0.458,0.268,0.969,0.397,1.48,0.397c0.511,0,1.022-0.133,1.48-0.397l36.098-20.84
|
|
||||||
c0.918-0.529,1.479-1.506,1.479-2.564S44.247,21.767,43.331,21.237z"/>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
Before Width: | Height: | Size: 811 B |
10
svg/play.svg
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
|
||||||
|
<svg version="1.0" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 5010 5000" preserveAspectRatio="xMidYMid meet">
|
||||||
|
<g id="layer1" fill="#ffffff" stroke="none">
|
||||||
|
<path d="M1395 4388 c-3 -7 -4 -870 -3 -1918 3 -1803 4 -1905 20 -1905 24 0 2658 1893 2658 1910 0 14 -2628 1918 -2654 1923 -9 2 -18 -2 -21 -10z"/>
|
||||||
|
</g>
|
||||||
|
<g id="layer2" fill="#1134c1" stroke="none">
|
||||||
|
<path d="M0 2500 l0 -2500 2505 0 2505 0 0 2500 0 2500 -2505 0 -2505 0 0 -2500z m2751 942 c725 -525 1319 -960 1319 -967 0 -17 -2634 -1910 -2658 -1910 -16 0 -17 102 -20 1905 -1 1048 0 1911 3 1918 3 8 12 12 21 10 8 -2 609 -432 1335 -956z"/>
|
||||||
|
</g>
|
||||||
|
|
||||||
|
</svg>
|
After Width: | Height: | Size: 721 B |