aboutsummaryrefslogtreecommitdiff
path: root/src/plugins/Visual/analyzer
diff options
context:
space:
mode:
authortrialuser02 <trialuser02@90c681e8-e032-0410-971d-27865f9a5e38>2013-11-01 07:27:49 +0000
committertrialuser02 <trialuser02@90c681e8-e032-0410-971d-27865f9a5e38>2013-11-01 07:27:49 +0000
commit680774d70ccd39a6eb395d446d3d0a3f06242b92 (patch)
tree2d19a5f020359fd4a91f4e5ae8756e17570ee6c3 /src/plugins/Visual/analyzer
parentccc5b120fa1380de83bae6e509eca8aea0a6519c (diff)
downloadqmmp-680774d70ccd39a6eb395d446d3d0a3f06242b92.tar.gz
qmmp-680774d70ccd39a6eb395d446d3d0a3f06242b92.tar.bz2
qmmp-680774d70ccd39a6eb395d446d3d0a3f06242b92.zip
analyzer: added context menu
git-svn-id: http://svn.code.sf.net/p/qmmp-dev/code/trunk/qmmp@3851 90c681e8-e032-0410-971d-27865f9a5e38
Diffstat (limited to 'src/plugins/Visual/analyzer')
-rw-r--r--src/plugins/Visual/analyzer/analyzer.cpp205
-rw-r--r--src/plugins/Visual/analyzer/analyzer.h34
-rw-r--r--src/plugins/Visual/analyzer/settingsdialog.cpp38
-rw-r--r--src/plugins/Visual/analyzer/settingsdialog.ui150
4 files changed, 211 insertions, 216 deletions
diff --git a/src/plugins/Visual/analyzer/analyzer.cpp b/src/plugins/Visual/analyzer/analyzer.cpp
index 7e3578ec6..d7cb683d0 100644
--- a/src/plugins/Visual/analyzer/analyzer.cpp
+++ b/src/plugins/Visual/analyzer/analyzer.cpp
@@ -1,5 +1,5 @@
/***************************************************************************
- * Copyright (C) 2007-2012 by Ilya Kotov *
+ * Copyright (C) 2007-2013 by Ilya Kotov *
* forkotov02@hotmail.ru *
* *
* This program is free software; you can redistribute it and/or modify *
@@ -22,12 +22,11 @@
#include <QPainter>
#include <QMenu>
#include <QActionGroup>
-
-#include <qmmp/buffer.h>
-#include <qmmp/output.h>
+#include <QPaintEvent>
#include <math.h>
#include <stdlib.h>
-
+#include <qmmp/buffer.h>
+#include <qmmp/output.h>
#include "fft.h"
#include "inlines.h"
#include "analyzer.h"
@@ -35,7 +34,7 @@
#define VISUAL_NODE_SIZE 512 //samples
#define VISUAL_BUFFER_SIZE (5*VISUAL_NODE_SIZE)
-Analyzer::Analyzer (QWidget *parent) : Visual (parent), m_fps (20)
+Analyzer::Analyzer (QWidget *parent) : Visual (parent)
{
m_intern_vis_data = 0;
m_peaks = 0;
@@ -43,9 +42,9 @@ Analyzer::Analyzer (QWidget *parent) : Visual (parent), m_fps (20)
m_buffer_at = 0;
m_rows = 0;
m_cols = 0;
- QSettings settings(Qmmp::configFile(), QSettings::IniFormat);
- restoreGeometry(settings.value("Analyzer/geometry").toByteArray());
- //setAttribute(Qt::WA_TranslucentBackground);
+ m_update = false;
+
+ setWindowTitle (tr("Qmmp Analyzer"));
setMinimumSize(2*300-30,105);
m_timer = new QTimer (this);
connect(m_timer, SIGNAL (timeout()), this, SLOT (timeout()));
@@ -53,30 +52,8 @@ Analyzer::Analyzer (QWidget *parent) : Visual (parent), m_fps (20)
m_right_buffer = new short[VISUAL_BUFFER_SIZE];
clear();
- setWindowTitle (tr("Qmmp Analyzer"));
-
- double peaks_speed[] = { 0.05, 0.1, 0.2, 0.4, 0.8 };
- double analyzer_speed[] = { 1.2, 1.8, 2.2, 2.4, 2.8 };
- int intervals[] = { 20 , 40 , 100 , 200 };
-
- m_peaks_falloff =
- peaks_speed[settings.value("Analyzer/peaks_falloff", 3).toInt()-1];
- m_analyzer_falloff =
- analyzer_speed[settings.value("Analyzer/analyzer_falloff", 3).toInt()-1];
- m_show_peaks = settings.value("Analyzer/show_peaks", true).toBool();
- m_timer->setInterval(intervals[settings.value("Analyzer/refresh_rate", 2).toInt() - 1]);
- m_color1.setNamedColor(settings.value("Analyzer/color1", "Green").toString());
- m_color2.setNamedColor(settings.value("Analyzer/color2", "Yellow").toString());
- m_color3.setNamedColor(settings.value("Analyzer/color3", "Red").toString());
- m_bgColor.setNamedColor(settings.value("Analyzer/bg_color", "Black").toString());
- //m_bgColor.setAlpha(0);
- m_peakColor.setNamedColor(settings.value("Analyzer/peak_color", "Cyan").toString());
- m_cell_size = settings.value("Analyzer/cells_size", QSize(15, 6)).toSize();
-
- QAction *fullScreenAction = new QAction(this);
- fullScreenAction->setShortcut(tr("F"));
- connect(fullScreenAction, SIGNAL(triggered()), SLOT(toggleFullScreen()));
- addAction(fullScreenAction);
+ createMenu();
+ readSettings();
}
Analyzer::~Analyzer()
@@ -92,14 +69,6 @@ Analyzer::~Analyzer()
delete [] m_x_scale;
}
-void Analyzer::clear()
-{
- m_buffer_at = 0;
- m_rows = 0;
- m_cols = 0;
- update();
-}
-
void Analyzer::add (unsigned char *data, qint64 size, int chan)
{
if (!m_timer->isActive ())
@@ -129,6 +98,15 @@ void Analyzer::add (unsigned char *data, qint64 size, int chan)
m_buffer_at += frames;
}
+void Analyzer::clear()
+{
+ m_buffer_at = 0;
+ m_rows = 0;
+ m_cols = 0;
+ update();
+}
+
+
void Analyzer::timeout()
{
mutex()->lock ();
@@ -146,11 +124,81 @@ void Analyzer::timeout()
update();
}
-void Analyzer::paintEvent (QPaintEvent * e)
+void Analyzer::toggleFullScreen()
{
- QPainter painter (this);
- painter.fillRect(e->rect(),m_bgColor);
- draw(&painter);
+ setWindowState(windowState() ^Qt::WindowFullScreen);
+}
+
+void Analyzer::readSettings()
+{
+ QSettings settings(Qmmp::configFile(), QSettings::IniFormat);
+ settings.beginGroup("Analyzer");
+ m_peaks_falloff = settings.value("peak_falloff", 0.2).toDouble();
+ m_analyzer_falloff = settings.value("analyzer_falloff", 2.2).toDouble();
+ m_show_peaks = settings.value("show_peaks", true).toBool();
+ m_timer->setInterval(1000 / settings.value("refresh_rate", 25).toInt());
+ m_color1.setNamedColor(settings.value("color1", "Green").toString());
+ m_color2.setNamedColor(settings.value("color2", "Yellow").toString());
+ m_color3.setNamedColor(settings.value("color3", "Red").toString());
+ m_bgColor.setNamedColor(settings.value("bg_color", "Black").toString());
+ m_peakColor.setNamedColor(settings.value("peak_color", "Cyan").toString());
+ m_cell_size = settings.value("cells_size", QSize(15, 6)).toSize();
+
+
+ if(!m_update)
+ {
+ m_update = true;
+ m_peaksAction->setChecked(m_show_peaks);
+
+ foreach(QAction *act, m_fpsGroup->actions ())
+ {
+ if (m_timer->interval() == 1000 / act->data().toInt())
+ act->setChecked(true);
+ }
+ foreach(QAction *act, m_peaksFalloffGroup->actions ())
+ {
+ if (m_peaks_falloff == act->data().toDouble())
+ act->setChecked(true);
+ }
+ foreach(QAction *act, m_analyzerFalloffGroup->actions ())
+ {
+ if (m_analyzer_falloff == act->data().toDouble())
+ act->setChecked(true);
+ }
+
+ //fallback
+ if(!m_fpsGroup->checkedAction())
+ {
+ m_fpsGroup->actions().at(1)->setChecked(true);
+ m_timer->setInterval(1000 / 25);
+ }
+ if(!m_peaksFalloffGroup->checkedAction())
+ {
+ m_peaksFalloffGroup->actions().at(1)->setChecked(2);
+ m_peaks_falloff = 0.2;
+ }
+ if(!m_peaksFalloffGroup->checkedAction())
+ {
+ m_peaksFalloffGroup->actions().at(1)->setChecked(2);
+ m_analyzer_falloff = 2.2;
+ }
+
+ restoreGeometry(settings.value("geometry").toByteArray());
+ }
+}
+
+void Analyzer::writeSettings()
+{
+ QSettings settings(Qmmp::configFile(), QSettings::IniFormat);
+ settings.beginGroup("Analyzer");
+ QAction *act = m_fpsGroup->checkedAction ();
+ settings.setValue("refresh_rate", act ? act->data().toInt() : 25);
+ act = m_peaksFalloffGroup->checkedAction ();
+ settings.setValue("peak_falloff", act ? act->data().toDouble() : 0.2);
+ act = m_analyzerFalloffGroup->checkedAction ();
+ settings.setValue("analyzer_falloff", act ? act->data().toDouble() : 2.2);
+ settings.setValue("show_peaks", m_peaksAction->isChecked());
+ settings.endGroup();
}
void Analyzer::hideEvent (QHideEvent *)
@@ -171,6 +219,19 @@ void Analyzer::closeEvent (QCloseEvent *event)
Visual::closeEvent(event); //removes visualization object
}
+void Analyzer::paintEvent (QPaintEvent * e)
+{
+ QPainter painter (this);
+ painter.fillRect(e->rect(),m_bgColor);
+ draw(&painter);
+}
+
+void Analyzer::mousePressEvent(QMouseEvent *e)
+{
+ if (e->button() == Qt::RightButton)
+ m_menu->exec(e->globalPos());
+}
+
void Analyzer::process (short *left, short *right)
{
static fft_state *state = 0;
@@ -294,7 +355,57 @@ void Analyzer::draw (QPainter *p)
}
}
-void Analyzer::toggleFullScreen()
+void Analyzer::createMenu()
{
- setWindowState(windowState() ^Qt::WindowFullScreen);
+ m_menu = new QMenu (this);
+ connect(m_menu, SIGNAL(triggered (QAction *)),SLOT(writeSettings()));
+ connect(m_menu, SIGNAL(triggered (QAction *)),SLOT(readSettings()));
+
+ m_peaksAction = m_menu->addAction(tr("Peaks"));
+ m_peaksAction->setCheckable(true);
+
+ QMenu *refreshRate = m_menu->addMenu(tr("Refresh Rate"));
+ m_fpsGroup = new QActionGroup(this);
+ m_fpsGroup->setExclusive(true);
+ m_fpsGroup->addAction(tr("50 fps"))->setData(50);
+ m_fpsGroup->addAction(tr("25 fps"))->setData(25);
+ m_fpsGroup->addAction(tr("10 fps"))->setData(10);
+ m_fpsGroup->addAction(tr("5 fps"))->setData(5);
+ foreach(QAction *act, m_fpsGroup->actions ())
+ {
+ act->setCheckable(true);
+ refreshRate->addAction(act);
+ }
+
+ QMenu *analyzerFalloff = m_menu->addMenu(tr("Analyzer Falloff"));
+ m_analyzerFalloffGroup = new QActionGroup(this);
+ m_analyzerFalloffGroup->setExclusive(true);
+ m_analyzerFalloffGroup->addAction(tr("Slowest"))->setData(1.2);
+ m_analyzerFalloffGroup->addAction(tr("Slow"))->setData(1.8);
+ m_analyzerFalloffGroup->addAction(tr("Medium"))->setData(2.2);
+ m_analyzerFalloffGroup->addAction(tr("Fast"))->setData(2.4);
+ m_analyzerFalloffGroup->addAction(tr("Fastest"))->setData(2.8);
+ foreach(QAction *act, m_analyzerFalloffGroup->actions ())
+ {
+ act->setCheckable(true);
+ analyzerFalloff->addAction(act);
+ }
+
+ QMenu *peaksFalloff = m_menu->addMenu(tr("Peaks Falloff"));
+ m_peaksFalloffGroup = new QActionGroup(this);
+ m_peaksFalloffGroup->setExclusive(true);
+ m_peaksFalloffGroup->addAction(tr("Slowest"))->setData(0.05);
+ m_peaksFalloffGroup->addAction(tr("Slow"))->setData(0.1);
+ m_peaksFalloffGroup->addAction(tr("Medium"))->setData(0.2);
+ m_peaksFalloffGroup->addAction(tr("Fast"))->setData(0.4);
+ m_peaksFalloffGroup->addAction(tr("Fastest"))->setData(0.8);
+ foreach(QAction *act, m_peaksFalloffGroup->actions ())
+ {
+ act->setCheckable(true);
+ peaksFalloff->addAction(act);
+ }
+ m_menu->addSeparator();
+ QAction *fullScreenAction = m_menu->addAction(tr("&Full Screen"), this, SLOT(toggleFullScreen()), tr("F"));
+ addAction(fullScreenAction);
+ update();
}
diff --git a/src/plugins/Visual/analyzer/analyzer.h b/src/plugins/Visual/analyzer/analyzer.h
index 74d8a1695..7de645ef5 100644
--- a/src/plugins/Visual/analyzer/analyzer.h
+++ b/src/plugins/Visual/analyzer/analyzer.h
@@ -1,5 +1,5 @@
/***************************************************************************
- * Copyright (C) 2007-2012 by Ilya Kotov *
+ * Copyright (C) 2007-2013 by Ilya Kotov *
* forkotov02@hotmail.ru *
* *
* This program is free software; you can redistribute it and/or modify *
@@ -21,12 +21,16 @@
#define ANALYZER_H
#include <QWidget>
-#include <QResizeEvent>
#include <qmmp/visual.h>
class QTimer;
class QMenu;
+class QAction;
class QActionGroup;
+class QPainter;
+class QPaintEvent;
+class QHideEvent;
+class QShowEvent;
class Analyzer : public Visual
@@ -39,25 +43,25 @@ public:
void add(unsigned char *data, qint64 size, int chan);
void clear();
- void paintEvent( QPaintEvent * );
-protected:
- virtual void hideEvent (QHideEvent *);
- virtual void showEvent (QShowEvent *);
- virtual void closeEvent (QCloseEvent *);
-
-public slots:
- void timeout();
private slots:
+ void timeout();
void toggleFullScreen();
+ void readSettings();
+ void writeSettings();
+
private:
+ virtual void hideEvent (QHideEvent *);
+ virtual void showEvent (QShowEvent *);
+ virtual void closeEvent (QCloseEvent *);
+ void paintEvent(QPaintEvent *);
+ void mousePressEvent(QMouseEvent *e);
void process(short *l, short *r);
void draw(QPainter *p);
- QPixmap m_bg;
+ void createMenu();
QTimer *m_timer;
- int m_fps;
double *m_intern_vis_data;
double *m_peaks;
int *m_x_scale;
@@ -68,6 +72,7 @@ private:
short *m_right_buffer;
int m_buffer_at;
int m_cols, m_rows;
+ bool m_update;
//colors
QColor m_color1;
QColor m_color2;
@@ -75,6 +80,11 @@ private:
QColor m_bgColor;
QColor m_peakColor;
QSize m_cell_size;
+ QMenu *m_menu;
+ QAction *m_peaksAction;
+ QActionGroup *m_fpsGroup;
+ QActionGroup *m_analyzerFalloffGroup;
+ QActionGroup *m_peaksFalloffGroup;
};
diff --git a/src/plugins/Visual/analyzer/settingsdialog.cpp b/src/plugins/Visual/analyzer/settingsdialog.cpp
index 444a303dd..664fae2b1 100644
--- a/src/plugins/Visual/analyzer/settingsdialog.cpp
+++ b/src/plugins/Visual/analyzer/settingsdialog.cpp
@@ -1,5 +1,5 @@
/***************************************************************************
- * Copyright (C) 2007-2012 by Ilya Kotov *
+ * Copyright (C) 2007-2013 by Ilya Kotov *
* forkotov02@hotmail.ru *
* *
* This program is free software; you can redistribute it and/or modify *
@@ -27,18 +27,16 @@ SettingsDialog::SettingsDialog(QWidget *parent) : QDialog(parent)
{
m_ui.setupUi(this);
QSettings settings(Qmmp::configFile(), QSettings::IniFormat);
- m_ui.analyzerComboBox->setCurrentIndex(settings.value("Analyzer/analyzer_falloff", 3).toInt()-1);
- m_ui.peaksCheckBox->setChecked(settings.value("Analyzer/show_peaks", true).toBool());
- m_ui.peaksComboBox->setCurrentIndex(settings.value("Analyzer/peaks_falloff", 3).toInt()-1);
- m_ui.fpsComboBox->setCurrentIndex(settings.value("Analyzer/refresh_rate", 2).toInt()-1);
- m_ui.colorWidget1->setColor(settings.value("Analyzer/color1", "Green").toString());
- m_ui.colorWidget2->setColor(settings.value("Analyzer/color2", "Yellow").toString());
- m_ui.colorWidget3->setColor(settings.value("Analyzer/color3", "Red").toString());
- m_ui.bgColorWidget->setColor(settings.value("Analyzer/bg_color", "Black").toString());
- m_ui.peakColorWidget->setColor(settings.value("Analyzer/peak_color", "Cyan").toString());
- QSize cells_size = settings.value("Analyzer/cells_size", QSize(15, 6)).toSize();
+ settings.beginGroup("Analyzer");
+ m_ui.colorWidget1->setColor(settings.value("color1", "Green").toString());
+ m_ui.colorWidget2->setColor(settings.value("color2", "Yellow").toString());
+ m_ui.colorWidget3->setColor(settings.value("color3", "Red").toString());
+ m_ui.bgColorWidget->setColor(settings.value("bg_color", "Black").toString());
+ m_ui.peakColorWidget->setColor(settings.value("peak_color", "Cyan").toString());
+ QSize cells_size = settings.value("cells_size", QSize(15, 6)).toSize();
m_ui.cellWidthSpinBox->setValue(cells_size.width());
m_ui.cellHeightSpinBox->setValue(cells_size.height());
+ settings.endGroup();
}
SettingsDialog::~SettingsDialog()
@@ -48,16 +46,14 @@ SettingsDialog::~SettingsDialog()
void SettingsDialog::accept()
{
QSettings settings(Qmmp::configFile(), QSettings::IniFormat);
- settings.setValue("Analyzer/analyzer_falloff", m_ui.analyzerComboBox->currentIndex() + 1);
- settings.setValue("Analyzer/peaks_falloff", m_ui.peaksComboBox->currentIndex() + 1);
- settings.setValue("Analyzer/refresh_rate", m_ui.fpsComboBox->currentIndex() + 1);
- settings.setValue("Analyzer/show_peaks", m_ui.peaksCheckBox->isChecked());
- settings.setValue("Analyzer/color1", m_ui.colorWidget1->colorName());
- settings.setValue("Analyzer/color2", m_ui.colorWidget2->colorName());
- settings.setValue("Analyzer/color3", m_ui.colorWidget3->colorName());
- settings.setValue("Analyzer/bg_color", m_ui.bgColorWidget->colorName());
- settings.setValue("Analyzer/peak_color", m_ui.peakColorWidget->colorName());
- settings.setValue("Analyzer/cells_size", QSize(m_ui.cellWidthSpinBox->value(),
+ settings.beginGroup("Analyzer");
+ settings.setValue("color1", m_ui.colorWidget1->colorName());
+ settings.setValue("color2", m_ui.colorWidget2->colorName());
+ settings.setValue("color3", m_ui.colorWidget3->colorName());
+ settings.setValue("bg_color", m_ui.bgColorWidget->colorName());
+ settings.setValue("peak_color", m_ui.peakColorWidget->colorName());
+ settings.setValue("cells_size", QSize(m_ui.cellWidthSpinBox->value(),
m_ui.cellHeightSpinBox->value()));
+ settings.endGroup();
QDialog::accept();
}
diff --git a/src/plugins/Visual/analyzer/settingsdialog.ui b/src/plugins/Visual/analyzer/settingsdialog.ui
index b781ea5c8..d588626b9 100644
--- a/src/plugins/Visual/analyzer/settingsdialog.ui
+++ b/src/plugins/Visual/analyzer/settingsdialog.ui
@@ -6,14 +6,23 @@
<rect>
<x>0</x>
<y>0</y>
- <width>314</width>
- <height>310</height>
+ <width>312</width>
+ <height>223</height>
</rect>
</property>
<property name="windowTitle">
<string>Analyzer Plugin Settings</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
+ <property name="leftMargin">
+ <number>6</number>
+ </property>
+ <property name="rightMargin">
+ <number>6</number>
+ </property>
+ <property name="bottomMargin">
+ <number>6</number>
+ </property>
<item>
<widget class="QGroupBox" name="groupBox_2">
<property name="sizePolicy">
@@ -25,146 +34,15 @@
<property name="title">
<string>General</string>
</property>
- <layout class="QGridLayout" name="gridLayout">
- <item row="0" column="0" colspan="2">
- <widget class="QCheckBox" name="peaksCheckBox">
- <property name="layoutDirection">
- <enum>Qt::LeftToRight</enum>
- </property>
- <property name="text">
- <string>Show peaks</string>
- </property>
- </widget>
- </item>
- <item row="1" column="0">
- <widget class="QLabel" name="label_10">
- <property name="text">
- <string>Analyzer falloff:</string>
- </property>
- <property name="alignment">
- <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
- </property>
- </widget>
- </item>
- <item row="1" column="1">
- <widget class="QComboBox" name="analyzerComboBox">
- <property name="currentIndex">
- <number>2</number>
- </property>
- <item>
- <property name="text">
- <string>Slowest</string>
- </property>
- </item>
- <item>
- <property name="text">
- <string>Slow</string>
- </property>
- </item>
- <item>
- <property name="text">
- <string>Medium</string>
- </property>
- </item>
- <item>
- <property name="text">
- <string>Fast</string>
- </property>
- </item>
- <item>
- <property name="text">
- <string>Fastest</string>
- </property>
- </item>
- </widget>
- </item>
- <item row="2" column="0">
- <widget class="QLabel" name="label_9">
- <property name="text">
- <string>Peaks falloff:</string>
- </property>
- <property name="alignment">
- <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
- </property>
- </widget>
- </item>
- <item row="2" column="1">
- <widget class="QComboBox" name="peaksComboBox">
- <property name="currentIndex">
- <number>2</number>
- </property>
- <item>
- <property name="text">
- <string>Slowest</string>
- </property>
- </item>
- <item>
- <property name="text">
- <string>Slow</string>
- </property>
- </item>
- <item>
- <property name="text">
- <string>Medium</string>
- </property>
- </item>
- <item>
- <property name="text">
- <string>Fast</string>
- </property>
- </item>
- <item>
- <property name="text">
- <string>Fastest</string>
- </property>
- </item>
- </widget>
- </item>
- <item row="3" column="0">
- <widget class="QLabel" name="label_11">
- <property name="text">
- <string>Refresh rate:</string>
- </property>
- <property name="alignment">
- <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
- </property>
- </widget>
- </item>
- <item row="3" column="1">
- <widget class="QComboBox" name="fpsComboBox">
- <property name="currentIndex">
- <number>0</number>
- </property>
- <item>
- <property name="text">
- <string>50 FPS</string>
- </property>
- </item>
- <item>
- <property name="text">
- <string>25 FPS</string>
- </property>
- </item>
- <item>
- <property name="text">
- <string>10 FPS</string>
- </property>
- </item>
- <item>
- <property name="text">
- <string>5 FPS</string>
- </property>
- </item>
- </widget>
- </item>
- <item row="4" column="0">
+ <layout class="QFormLayout" name="formLayout">
+ <item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Cells size:</string>
</property>
</widget>
</item>
- <item row="4" column="1">
+ <item row="0" column="1">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QSpinBox" name="cellWidthSpinBox">