diff --git a/DSView/DSView.qrc b/DSView/DSView.qrc
index 05955d6d..76bf2800 100644
--- a/DSView/DSView.qrc
+++ b/DSView/DSView.qrc
@@ -56,5 +56,6 @@
icons/start_dis.png
icons/start_dis_cn.png
icons/settings.png
+ darkstyle/style.qss
diff --git a/DSView/darkstyle/style.qss b/DSView/darkstyle/style.qss
new file mode 100755
index 00000000..baa433ed
--- /dev/null
+++ b/DSView/darkstyle/style.qss
@@ -0,0 +1,1218 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) <2013-2014>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+QProgressBar:horizontal {
+ border: 1px solid #3A3939;
+ text-align: center;
+ padding: 1px;
+ background: #201F1F;
+}
+QProgressBar::chunk:horizontal {
+ background-color: qlineargradient(spread:reflect, x1:1, y1:0.545, x2:1, y2:0, stop:0 rgba(28, 66, 111, 255), stop:1 rgba(37, 87, 146, 255));
+}
+
+QToolTip
+{
+ border: 1px solid #3A3939;
+ background-color: rgb(90, 102, 117);;
+ color: white;
+ padding: 1px;
+ opacity: 200;
+}
+
+QWidget
+{
+ color: silver;
+ background-color: #302F2F;
+ selection-background-color:#3d8ec9;
+ selection-color: black;
+ background-clip: border;
+ border-image: none;
+ outline: 0;
+}
+
+QWidget:item:hover
+{
+ background-color: #78879b;
+ color: black;
+}
+
+QWidget:item:selected
+{
+ background-color: #3d8ec9;
+}
+
+QCheckBox
+{
+ spacing: 5px;
+ outline: none;
+ color: #bbb;
+ margin-bottom: 2px;
+}
+
+QCheckBox:disabled
+{
+ color: #777777;
+}
+QCheckBox::indicator,
+QGroupBox::indicator
+{
+ width: 18px;
+ height: 18px;
+}
+QGroupBox::indicator
+{
+ margin-left: 2px;
+}
+
+QCheckBox::indicator:unchecked,
+QCheckBox::indicator:unchecked:hover,
+QGroupBox::indicator:unchecked,
+QGroupBox::indicator:unchecked:hover
+{
+ image: url(:/qss_icons/rc/checkbox_unchecked.png);
+}
+
+QCheckBox::indicator:unchecked:focus,
+QCheckBox::indicator:unchecked:pressed,
+QGroupBox::indicator:unchecked:focus,
+QGroupBox::indicator:unchecked:pressed
+{
+ border: none;
+ image: url(:/qss_icons/rc/checkbox_unchecked_focus.png);
+}
+
+QCheckBox::indicator:checked,
+QCheckBox::indicator:checked:hover,
+QGroupBox::indicator:checked,
+QGroupBox::indicator:checked:hover
+{
+ image: url(:/qss_icons/rc/checkbox_checked.png);
+}
+
+QCheckBox::indicator:checked:focus,
+QCheckBox::indicator:checked:pressed,
+QGroupBox::indicator:checked:focus,
+QGroupBox::indicator:checked:pressed
+{
+ border: none;
+ image: url(:/qss_icons/rc/checkbox_checked_focus.png);
+}
+
+QCheckBox::indicator:indeterminate,
+QCheckBox::indicator:indeterminate:hover,
+QCheckBox::indicator:indeterminate:pressed
+QGroupBox::indicator:indeterminate,
+QGroupBox::indicator:indeterminate:hover,
+QGroupBox::indicator:indeterminate:pressed
+{
+ image: url(:/qss_icons/rc/checkbox_indeterminate.png);
+}
+
+QCheckBox::indicator:indeterminate:focus,
+QGroupBox::indicator:indeterminate:focus
+{
+ image: url(:/qss_icons/rc/checkbox_indeterminate_focus.png);
+}
+
+QCheckBox::indicator:checked:disabled,
+QGroupBox::indicator:checked:disabled
+{
+ image: url(:/qss_icons/rc/checkbox_checked_disabled.png);
+}
+
+QCheckBox::indicator:unchecked:disabled,
+QGroupBox::indicator:unchecked:disabled
+{
+ image: url(:/qss_icons/rc/checkbox_unchecked_disabled.png);
+}
+
+QRadioButton
+{
+ spacing: 5px;
+ outline: none;
+ color: #bbb;
+ margin-bottom: 2px;
+}
+
+QRadioButton:disabled
+{
+ color: #777777;
+}
+QRadioButton::indicator
+{
+ width: 21px;
+ height: 21px;
+}
+
+QRadioButton::indicator:unchecked,
+QRadioButton::indicator:unchecked:hover
+{
+ image: url(:/qss_icons/rc/radio_unchecked.png);
+}
+
+QRadioButton::indicator:unchecked:focus,
+QRadioButton::indicator:unchecked:pressed
+{
+ border: none;
+ outline: none;
+ image: url(:/qss_icons/rc/radio_unchecked_focus.png);
+}
+
+QRadioButton::indicator:checked,
+QRadioButton::indicator:checked:hover
+{
+ border: none;
+ outline: none;
+ image: url(:/qss_icons/rc/radio_checked.png);
+}
+
+QRadioButton::indicator:checked:focus,
+QRadioButton::indicato::menu-arrowr:checked:pressed
+{
+ border: none;
+ outline: none;
+ image: url(:/qss_icons/rc/radio_checked_focus.png);
+}
+
+QRadioButton::indicator:indeterminate,
+QRadioButton::indicator:indeterminate:hover,
+QRadioButton::indicator:indeterminate:pressed
+{
+ image: url(:/qss_icons/rc/radio_indeterminate.png);
+}
+
+QRadioButton::indicator:checked:disabled
+{
+ outline: none;
+ image: url(:/qss_icons/rc/radio_checked_disabled.png);
+}
+
+QRadioButton::indicator:unchecked:disabled
+{
+ image: url(:/qss_icons/rc/radio_unchecked_disabled.png);
+}
+
+
+QMenuBar
+{
+ background-color: #302F2F;
+ color: silver;
+}
+
+QMenuBar::item
+{
+ background: transparent;
+}
+
+QMenuBar::item:selected
+{
+ background: transparent;
+ border: 1px solid #3A3939;
+}
+
+QMenuBar::item:pressed
+{
+ border: 1px solid #3A3939;
+ background-color: #3d8ec9;
+ color: black;
+ margin-bottom:-1px;
+ padding-bottom:1px;
+}
+
+QMenu
+{
+ border: 1px solid #3A3939;
+ color: silver;
+ margin: 2px;
+}
+
+QMenu::icon
+{
+ margin: 5px;
+}
+
+QMenu::item
+{
+ padding: 5px 30px 5px 30px;
+ margin-left: 5px;
+ border: 1px solid transparent; /* reserve space for selection border */
+}
+
+QMenu::item:selected
+{
+ color: black;
+}
+
+QMenu::separator {
+ height: 2px;
+ background: lightblue;
+ margin-left: 10px;
+ margin-right: 5px;
+}
+
+QMenu::indicator {
+ width: 18px;
+ height: 18px;
+}
+
+/* non-exclusive indicator = check box style indicator
+ (see QActionGroup::setExclusive) */
+QMenu::indicator:non-exclusive:unchecked {
+ image: url(:/qss_icons/rc/checkbox_unchecked.png);
+}
+
+QMenu::indicator:non-exclusive:unchecked:selected {
+ image: url(:/qss_icons/rc/checkbox_unchecked_disabled.png);
+}
+
+QMenu::indicator:non-exclusive:checked {
+ image: url(:/qss_icons/rc/checkbox_checked.png);
+}
+
+QMenu::indicator:non-exclusive:checked:selected {
+ image: url(:/qss_icons/rc/checkbox_checked_disabled.png);
+}
+
+/* exclusive indicator = radio button style indicator (see QActionGroup::setExclusive) */
+QMenu::indicator:exclusive:unchecked {
+ image: url(:/qss_icons/rc/radio_unchecked.png);
+}
+
+QMenu::indicator:exclusive:unchecked:selected {
+ image: url(:/qss_icons/rc/radio_unchecked_disabled.png);
+}
+
+QMenu::indicator:exclusive:checked {
+ image: url(:/qss_icons/rc/radio_checked.png);
+}
+
+QMenu::indicator:exclusive:checked:selected {
+ image: url(:/qss_icons/rc/radio_checked_disabled.png);
+}
+
+QMenu::right-arrow {
+ margin: 5px;
+ image: url(:/qss_icons/rc/right_arrow.png)
+}
+
+
+QWidget:disabled
+{
+ color: #404040;
+ background-color: #302F2F;
+}
+
+QAbstractItemView
+{
+ alternate-background-color: #3A3939;
+ color: silver;
+ border: 1px solid 3A3939;
+ border-radius: 2px;
+ padding: 1px;
+}
+
+QTabWidget:focus, QCheckBox:focus, QRadioButton:focus, QSlider:focus
+{
+ border: none;
+}
+
+QLineEdit
+{
+ background-color: #201F1F;
+ padding: 2px;
+ border-style: solid;
+ border: 1px solid #3A3939;
+ border-radius: 2px;
+ color: silver;
+}
+
+QGroupBox {
+ border:1px solid #3A3939;
+ border-radius: 2px;
+ margin-top: 20px;
+}
+
+QGroupBox::title {
+ subcontrol-origin: margin;
+ subcontrol-position: top center;
+ padding-left: 10px;
+ padding-right: 10px;
+ padding-top: 10px;
+}
+
+QScrollBar:horizontal
+{
+ height: 15px;
+ margin: 3px 15px 3px 15px;
+ border: 1px transparent #2A2929;
+ border-radius: 4px;
+ background-color: #2A2929;
+}
+
+QScrollBar::handle:horizontal
+{
+ background-color: #605F5F;
+ min-width: 5px;
+ border-radius: 4px;
+}
+
+QScrollBar::add-line:horizontal
+{
+ margin: 0px 3px 0px 3px;
+ border-image: url(:/qss_icons/rc/right_arrow_disabled.png);
+ width: 10px;
+ height: 10px;
+ subcontrol-position: right;
+ subcontrol-origin: margin;
+}
+
+QScrollBar::sub-line:horizontal
+{
+ margin: 0px 3px 0px 3px;
+ border-image: url(:/qss_icons/rc/left_arrow_disabled.png);
+ height: 10px;
+ width: 10px;
+ subcontrol-position: left;
+ subcontrol-origin: margin;
+}
+
+QScrollBar::add-line:horizontal:hover,QScrollBar::add-line:horizontal:on
+{
+ border-image: url(:/qss_icons/rc/right_arrow.png);
+ height: 10px;
+ width: 10px;
+ subcontrol-position: right;
+ subcontrol-origin: margin;
+}
+
+
+QScrollBar::sub-line:horizontal:hover, QScrollBar::sub-line:horizontal:on
+{
+ border-image: url(:/qss_icons/rc/left_arrow.png);
+ height: 10px;
+ width: 10px;
+ subcontrol-position: left;
+ subcontrol-origin: margin;
+}
+
+QScrollBar::up-arrow:horizontal, QScrollBar::down-arrow:horizontal
+{
+ background: none;
+}
+
+
+QScrollBar::add-page:horizontal, QScrollBar::sub-page:horizontal
+{
+ background: none;
+}
+
+QScrollBar:vertical
+{
+ background-color: #2A2929;
+ width: 15px;
+ margin: 15px 3px 15px 3px;
+ border: 1px transparent #2A2929;
+ border-radius: 4px;
+}
+
+QScrollBar::handle:vertical
+{
+ background-color: #605F5F;
+ min-height: 5px;
+ border-radius: 4px;
+}
+
+QScrollBar::sub-line:vertical
+{
+ margin: 3px 0px 3px 0px;
+ border-image: url(:/qss_icons/rc/up_arrow_disabled.png);
+ height: 10px;
+ width: 10px;
+ subcontrol-position: top;
+ subcontrol-origin: margin;
+}
+
+QScrollBar::add-line:vertical
+{
+ margin: 3px 0px 3px 0px;
+ border-image: url(:/qss_icons/rc/down_arrow_disabled.png);
+ height: 10px;
+ width: 10px;
+ subcontrol-position: bottom;
+ subcontrol-origin: margin;
+}
+
+QScrollBar::sub-line:vertical:hover,QScrollBar::sub-line:vertical:on
+{
+
+ border-image: url(:/qss_icons/rc/up_arrow.png);
+ height: 10px;
+ width: 10px;
+ subcontrol-position: top;
+ subcontrol-origin: margin;
+}
+
+
+QScrollBar::add-line:vertical:hover, QScrollBar::add-line:vertical:on
+{
+ border-image: url(:/qss_icons/rc/down_arrow.png);
+ height: 10px;
+ width: 10px;
+ subcontrol-position: bottom;
+ subcontrol-origin: margin;
+}
+
+QScrollBar::up-arrow:vertical, QScrollBar::down-arrow:vertical
+{
+ background: none;
+}
+
+
+QScrollBar::add-page:vertical, QScrollBar::sub-page:vertical
+{
+ background: none;
+}
+
+QTextEdit
+{
+ background-color: #201F1F;
+ color: silver;
+ border: 1px solid #3A3939;
+}
+
+QPlainTextEdit
+{
+ background-color: #201F1F;;
+ color: silver;
+ border-radius: 2px;
+ border: 1px solid #3A3939;
+}
+
+QHeaderView::section
+{
+ background-color: #3A3939;
+ color: silver;
+ padding-left: 4px;
+ border: 1px solid #6c6c6c;
+}
+
+QSizeGrip {
+ image: url(:/qss_icons/rc/sizegrip.png);
+ width: 12px;
+ height: 12px;
+}
+
+
+QMainWindow::separator
+{
+ background-color: QLinearGradient( x1: 0, y1: 0, x2: 0, y2: 1,
+ stop: 0.0 #302F2F,
+ stop: 0.4 #333333,
+ stop: 0.5 #404040,
+ stop: 0.6 #333333,
+ stop: 1 #302F2F);
+ color: white;
+ padding-left: 0px;
+ spacing: 0px;
+ width: 3px;
+ border: 0px solid #202020;
+}
+
+QMenu::separator
+{
+ height: 1px;
+ background-color: #3A3939;
+ color: white;
+ padding-left: 4px;
+ margin-left: 10px;
+ margin-right: 5px;
+}
+
+
+QFrame
+{
+ border-radius: 2px;
+ border: 1px solid #444;
+}
+
+QFrame[frameShape="0"]
+{
+ border-radius: 2px;
+ border: 1px transparent #444;
+}
+
+QStackedWidget
+{
+ border: 1px transparent black;
+}
+
+QToolBar {
+ border: 1px transparent #393838;
+ background: 1px solid #302F2F;
+ font-weight: bold;
+}
+
+QToolBar::handle:horizontal {
+ image: url(:/qss_icons/rc/Hmovetoolbar.png);
+}
+QToolBar::handle:vertical {
+ image: url(:/qss_icons/rc/Vmovetoolbar.png);
+}
+QToolBar::separator:horizontal {
+ image: url(:/qss_icons/rc/Hsepartoolbar.png);
+}
+QToolBar::separator:vertical {
+ image: url(:/qss_icons/rc/Vsepartoolbars.png);
+}
+
+QPushButton
+{
+ color: silver;
+ background-color: #302F2F;
+ border-width: 1px;
+ border-color: #202020;
+ border-style: solid;
+ padding-top: 5px;
+ padding-bottom: 5px;
+ padding-left: 5px;
+ padding-right: 5px;
+ border-radius: 5px;
+ outline: none;
+}
+
+QPushButton:disabled
+{
+ background-color: #302F2F;
+ border-width: 1px;
+ border-color: #3A3939;
+ border-style: solid;
+ padding-top: 5px;
+ padding-bottom: 5px;
+ padding-left: 10px;
+ padding-right: 10px;
+ border-radius: 5px;
+ color: #454545;
+}
+
+QComboBox
+{
+ selection-background-color: #3d8ec9;
+ background-color: #201F1F;
+ border-style: solid;
+ border: 1px solid #3A3939;
+ border-radius: 2px;
+ padding: 2px;
+ min-width: 75px;
+}
+
+QPushButton:checked{
+background-color: QLinearGradient( x1: 0, y1: 0, x2: 0, y2: 1,
+ stop: 0.0 #302F2F,
+ stop: 0.5 #6a6868,
+ stop: 1 #302F2F);
+}
+
+QPushButton:hover
+{
+background-color: QLinearGradient( x1: 0, y1: 0, x2: 0, y2: 1,
+ stop: 0.0 #302F2F, stop: 0.4 #4E4D4D,
+ stop: 0.5 #6a6868,
+ stop: 0.6 #4E4D4D, stop: 1 #302F2F);
+}
+
+QComboBox:hover,QAbstractSpinBox:hover,QLineEdit:hover,QTextEdit:hover,QPlainTextEdit:hover,QAbstractView:hover,QTreeView:hover
+{
+ border: 1px solid #78879b;
+ color: silver;
+}
+
+QComboBox:on
+{
+ background-color: #626873;
+ padding-top: 3px;
+ padding-left: 4px;
+ selection-background-color: #4a4a4a;
+}
+
+QComboBox QAbstractItemView
+{
+ background-color: #201F1F;
+ border-radius: 2px;
+ border: 1px solid #444;
+ selection-background-color: #3d8ec9;
+}
+
+QComboBox::drop-down
+{
+ subcontrol-origin: padding;
+ subcontrol-position: top right;
+ width: 15px;
+
+ border-left-width: 0px;
+ border-left-color: darkgray;
+ border-left-style: solid;
+ border-top-right-radius: 3px;
+ border-bottom-right-radius: 3px;
+}
+
+QComboBox::down-arrow
+{
+ image: url(:/qss_icons/rc/down_arrow_disabled.png);
+}
+
+QComboBox::down-arrow:on, QComboBox::down-arrow:hover,
+QComboBox::down-arrow:focus
+{
+ image: url(:/qss_icons/rc/down_arrow.png);
+}
+
+QAbstractSpinBox {
+ padding-top: 2px;
+ padding-bottom: 2px;
+ border: 1px solid #3A3939;
+ background-color: #201F1F;
+ color: silver;
+ border-radius: 2px;
+ min-width: 75px;
+}
+
+QAbstractSpinBox:up-button
+{
+ background-color: transparent;
+ subcontrol-origin: border;
+ subcontrol-position: center right;
+}
+
+QAbstractSpinBox:down-button
+{
+ background-color: transparent;
+ subcontrol-origin: border;
+ subcontrol-position: center left;
+}
+
+QAbstractSpinBox::up-arrow,QAbstractSpinBox::up-arrow:disabled,QAbstractSpinBox::up-arrow:off {
+ image: url(:/qss_icons/rc/up_arrow_disabled.png);
+ width: 10px;
+ height: 10px;
+}
+QAbstractSpinBox::up-arrow:hover
+{
+ image: url(:/qss_icons/rc/up_arrow.png);
+}
+
+
+QAbstractSpinBox::down-arrow,QAbstractSpinBox::down-arrow:disabled,QAbstractSpinBox::down-arrow:off
+{
+ image: url(:/qss_icons/rc/down_arrow_disabled.png);
+ width: 10px;
+ height: 10px;
+}
+QAbstractSpinBox::down-arrow:hover
+{
+ image: url(:/qss_icons/rc/down_arrow.png);
+}
+
+
+QLabel
+{
+ border: 0px solid black;
+}
+
+QTabWidget{
+ border: 1px transparent black;
+}
+
+QTabWidget::pane {
+ border: 1px transparent #444;
+ border-radius: 3px;
+ padding: 3px;
+}
+
+QTabBar
+{
+ qproperty-drawBase: 0;
+ left: 5px; /* move to the right by 5px */
+}
+
+QTabBar:focus
+{
+ border: 0px transparent black;
+}
+
+QTabBar::close-button {
+ image: url(:/qss_icons/rc/close.png);
+ background: transparent;
+}
+
+QTabBar::close-button:hover
+{
+ image: url(:/qss_icons/rc/close-hover.png);
+ background: transparent;
+}
+
+QTabBar::close-button:pressed {
+ image: url(:/qss_icons/rc/close-pressed.png);
+ background: transparent;
+}
+
+/* TOP TABS */
+QTabBar::tab:top {
+ color: #b1b1b1;
+ border: 1px solid #4A4949;
+ border-bottom: 1px transparent black;
+ background-color: #302F2F;
+ padding: 5px;
+ border-top-left-radius: 2px;
+ border-top-right-radius: 2px;
+}
+
+QTabBar::tab:top:!selected
+{
+ color: #b1b1b1;
+ background-color: #201F1F;
+ border: 1px transparent #4A4949;
+ border-bottom: 1px transparent #4A4949;
+ border-top-left-radius: 0px;
+ border-top-right-radius: 0px;
+}
+
+QTabBar::tab:top:!selected:hover {
+ background-color: #48576b;
+}
+
+/* BOTTOM TABS */
+QTabBar::tab:bottom {
+ color: #b1b1b1;
+ border: 1px solid #4A4949;
+ border-top: 1px transparent black;
+ background-color: #302F2F;
+ padding: 5px;
+ border-bottom-left-radius: 2px;
+ border-bottom-right-radius: 2px;
+}
+
+QTabBar::tab:bottom:!selected
+{
+ color: #b1b1b1;
+ background-color: #201F1F;
+ border: 1px transparent #4A4949;
+ border-top: 1px transparent #4A4949;
+ border-bottom-left-radius: 0px;
+ border-bottom-right-radius: 0px;
+}
+
+QTabBar::tab:bottom:!selected:hover {
+ background-color: #78879b;
+}
+
+/* LEFT TABS */
+QTabBar::tab:left {
+ color: #b1b1b1;
+ border: 1px solid #4A4949;
+ border-left: 1px transparent black;
+ background-color: #302F2F;
+ padding: 5px;
+ border-top-right-radius: 2px;
+ border-bottom-right-radius: 2px;
+}
+
+QTabBar::tab:left:!selected
+{
+ color: #b1b1b1;
+ background-color: #201F1F;
+ border: 1px transparent #4A4949;
+ border-right: 1px transparent #4A4949;
+ border-top-right-radius: 0px;
+ border-bottom-right-radius: 0px;
+}
+
+QTabBar::tab:left:!selected:hover {
+ background-color: #48576b;
+}
+
+
+/* RIGHT TABS */
+QTabBar::tab:right {
+ color: #b1b1b1;
+ border: 1px solid #4A4949;
+ border-right: 1px transparent black;
+ background-color: #302F2F;
+ padding: 5px;
+ border-top-left-radius: 2px;
+ border-bottom-left-radius: 2px;
+}
+
+QTabBar::tab:right:!selected
+{
+ color: #b1b1b1;
+ background-color: #201F1F;
+ border: 1px transparent #4A4949;
+ border-right: 1px transparent #4A4949;
+ border-top-left-radius: 0px;
+ border-bottom-left-radius: 0px;
+}
+
+QTabBar::tab:right:!selected:hover {
+ background-color: #48576b;
+}
+
+QTabBar QToolButton::right-arrow:enabled {
+ image: url(:/qss_icons/rc/right_arrow.png);
+ }
+
+ QTabBar QToolButton::left-arrow:enabled {
+ image: url(:/qss_icons/rc/left_arrow.png);
+ }
+
+QTabBar QToolButton::right-arrow:disabled {
+ image: url(:/qss_icons/rc/right_arrow_disabled.png);
+ }
+
+ QTabBar QToolButton::left-arrow:disabled {
+ image: url(:/qss_icons/rc/left_arrow_disabled.png);
+ }
+
+
+QDockWidget {
+ border: 1px transparent #403F3F;
+ titlebar-close-icon: url(:/qss_icons/rc/close.png);
+ titlebar-normal-icon: url(:/qss_icons/rc/undock.png);
+}
+
+QDockWidget::close-button, QDockWidget::float-button {
+ border: 1px solid transparent;
+ border-radius: 2px;
+ background: transparent;
+}
+
+QDockWidget::close-button:hover, QDockWidget::float-button:hover {
+ background: rgba(255, 255, 255, 10);
+}
+
+QDockWidget::close-button:pressed, QDockWidget::float-button:pressed {
+ padding: 1px -1px -1px 1px;
+ background: rgba(255, 255, 255, 10);
+}
+
+QTreeView, QListView
+{
+ border: 1px solid #444;
+ background-color: #201F1F;
+}
+
+QTreeView:branch:selected, QTreeView:branch:hover
+{
+ background: url(:/qss_icons/rc/transparent.png);
+}
+
+QTreeView::branch:has-siblings:!adjoins-item {
+ border-image: url(:/qss_icons/rc/transparent.png);
+}
+
+QTreeView::branch:has-siblings:adjoins-item {
+ border-image: url(:/qss_icons/rc/transparent.png);
+}
+
+QTreeView::branch:!has-children:!has-siblings:adjoins-item {
+ border-image: url(:/qss_icons/rc/transparent.png);
+}
+
+QTreeView::branch:has-children:!has-siblings:closed,
+QTreeView::branch:closed:has-children:has-siblings {
+ image: url(:/qss_icons/rc/branch_closed.png);
+}
+
+QTreeView::branch:open:has-children:!has-siblings,
+QTreeView::branch:open:has-children:has-siblings {
+ image: url(:/qss_icons/rc/branch_open.png);
+}
+
+QTreeView::branch:has-children:!has-siblings:closed:hover,
+QTreeView::branch:closed:has-children:has-siblings:hover {
+ image: url(:/qss_icons/rc/branch_closed-on.png);
+ }
+
+QTreeView::branch:open:has-children:!has-siblings:hover,
+QTreeView::branch:open:has-children:has-siblings:hover {
+ image: url(:/qss_icons/rc/branch_open-on.png);
+ }
+
+QListView::item:!selected:hover, QListView::item:!selected:hover, QTreeView::item:!selected:hover {
+ background: rgba(0, 0, 0, 0);
+ outline: 0;
+ color: #FFFFFF
+}
+
+QListView::item:selected:hover, QListView::item:selected:hover, QTreeView::item:selected:hover {
+ background: #3d8ec9;
+ color: #FFFFFF;
+}
+
+QSlider::groove:horizontal {
+ border: 1px solid #3A3939;
+ height: 8px;
+ background: #201F1F;
+ margin: 2px 0;
+ border-radius: 2px;
+}
+
+QSlider::handle:horizontal {
+ background: QLinearGradient( x1: 0, y1: 0, x2: 0, y2: 1,
+ stop: 0.0 silver, stop: 0.2 #a8a8a8, stop: 1 #727272);
+ border: 1px solid #3A3939;
+ width: 14px;
+ height: 14px;
+ margin: -4px 0;
+ border-radius: 2px;
+}
+
+QSlider::groove:vertical {
+ border: 1px solid #3A3939;
+ width: 8px;
+ background: #201F1F;
+ margin: 0 0px;
+ border-radius: 2px;
+}
+
+QSlider::handle:vertical {
+ background: QLinearGradient( x1: 0, y1: 0, x2: 0, y2: 1, stop: 0.0 silver,
+ stop: 0.2 #a8a8a8, stop: 1 #727272);
+ border: 1px solid #3A3939;
+ width: 14px;
+ height: 14px;
+ margin: 0 -4px;
+ border-radius: 2px;
+}
+
+QToolButton {
+ background-color: transparent;
+ border: 1px transparent #4A4949;
+ border-radius: 2px;
+ margin: 3px;
+ padding: 3px;
+}
+
+QToolButton[popupMode="1"] { /* only for MenuButtonPopup */
+ padding-right: 20px; /* make way for the popup button */
+ border: 1px transparent #4A4949;
+ border-radius: 5px;
+}
+
+QToolButton[popupMode="2"] { /* only for InstantPopup */
+ padding-right: 10px; /* make way for the popup button */
+ border: 1px transparent #4A4949;
+}
+
+
+QToolButton:hover, QToolButton::menu-button:hover {
+ background-color: QLinearGradient( x1: 0, y1: 0, x2: 0, y2: 1,
+ stop: 0.0 #302F2F, stop: 0.4 #4E4D4D,
+ stop: 0.5 #4A4949,
+ stop: 0.6 #4E4D4D, stop: 1 #302F2F);
+}
+
+QToolButton:checked, QToolButton:pressed,
+QToolButton::menu-button:pressed {
+ background-color: QLinearGradient( x1: 0, y1: 0, x2: 0, y2: 1,
+ stop: 0.0 #302F2F,
+ stop: 0.5 #4A4949,
+ stop: 1.0 #302F2F);
+}
+
+/* the subcontrol below is used only in the InstantPopup or DelayedPopup mode */
+QToolButton::menu-indicator {
+ image: url(:/qss_icons/rc/down_arrow.png);
+ top: -7px; left: -2px; /* shift it a bit */
+}
+
+/* the subcontrols below are used only in the MenuButtonPopup mode */
+QToolButton::menu-button {
+ border: 1px transparent #4A4949;
+ border-top-right-radius: 6px;
+ border-bottom-right-radius: 6px;
+ /* 16px width + 4px for border = 20px allocated above */
+ width: 16px;
+ outline: none;
+}
+
+QToolButton::menu-arrow {
+ image: url(:/qss_icons/rc/down_arrow.png);
+}
+
+QToolButton::menu-arrow:open {
+ top: 1px; left: 1px; /* shift it a bit */
+ border: 1px solid #3A3939;
+}
+
+QPushButton::menu-indicator {
+ subcontrol-origin: padding;
+ subcontrol-position: bottom right;
+ left: 8px;
+}
+
+QTableView
+{
+ border: 1px transparent #444;
+ gridline-color: #6c6c6c;
+ background-color: #201F1F;
+}
+
+
+QTableView, QHeaderView
+{
+ border-radius: 0px;
+}
+
+QTableView::item:pressed, QListView::item:pressed, QTreeView::item:pressed {
+ background: #78879b;
+ color: #FFFFFF;
+}
+
+QTableView::item:selected:active, QTreeView::item:selected:active, QListView::item:selected:active {
+ background: #3d8ec9;
+ color: #FFFFFF;
+}
+
+QHeaderView
+{
+ border: 1px transparent;
+ border-radius: 2px;
+ margin: 0px;
+ padding: 0px;
+}
+
+QHeaderView::section {
+ background-color: #302F2F;
+ color: silver;
+ padding: 4px;
+ border: 1px transparent #6c6c6c;
+ border-radius: 0px;
+ text-align: center;
+}
+
+QHeaderView::section::vertical::first, QHeaderView::section::vertical::only-one
+{
+ border-top: 1px transparent #6c6c6c;
+}
+
+QHeaderView::section::vertical
+{
+ border-top: transparent;
+}
+
+QHeaderView::section::horizontal::first, QHeaderView::section::horizontal::only-one
+{
+ border-left: 1px transparent #6c6c6c;
+}
+
+QHeaderView::section::horizontal
+{
+ border-left: transparent;
+}
+
+
+QHeaderView::section:checked
+ {
+ color: white;
+ background-color: #5A5959;
+ }
+
+ /* style the sort indicator */
+QHeaderView::down-arrow {
+ image: url(:/qss_icons/rc/down_arrow.png);
+}
+
+QHeaderView::up-arrow {
+ image: url(:/qss_icons/rc/up_arrow.png);
+}
+
+
+QTableCornerButton::section {
+ background-color: #3A3939;
+ border: 1px solid #3A3939;
+ border-radius: 2px;
+}
+
+QToolBox {
+ padding: 3px;
+ border: 1px transparent black;
+}
+
+QToolBox::tab {
+ color: #b1b1b1;
+ background-color: #302F2F;
+ border: 1px solid #4A4949;
+ border-bottom: 1px transparent #302F2F;
+ border-top-left-radius: 5px;
+ border-top-right-radius: 5px;
+}
+
+ QToolBox::tab:selected { /* italicize selected tabs */
+ font: italic;
+ background-color: #302F2F;
+ border-color: #3d8ec9;
+ }
+
+QStatusBar::item {
+ border: 1px solid #3A3939;
+ border-radius: 2px;
+ }
+
+
+QFrame[height="3"], QFrame[width="3"] {
+ background-color: #444;
+}
+
+
+QSplitter::handle {
+ border: 0px dashed #3A3939;
+}
+
+QSplitter::handle:horizontal {
+ background-color: QLinearGradient( x1: 0, y1: 0, x2: 0, y2: 1,
+ stop: 0.0 #302F2F,
+ stop: 0.4 #333333,
+ stop: 0.5 #404040,
+ stop: 0.6 #333333,
+ stop: 1 #302F2F);
+ width: 3px;
+}
+
+QSplitter::handle:vertical {
+ background-color: QLinearGradient( x1: 0, y1: 0, x2: 1, y2: 0,
+ stop: 0.0 #302F2F,
+ stop: 0.4 #333333,
+ stop: 0.5 #404040,
+ stop: 0.6 #333333,
+ stop: 1 #302F2F);
+ height: 3px;
+}
+
+QAbstractScrollArea
+{
+ border-radius: 2px;
+ border: 0px transparent #3A3939;
+ background-color: #302F2F;
+}
diff --git a/DSView/main.cpp b/DSView/main.cpp
index bd131f65..60876c69 100644
--- a/DSView/main.cpp
+++ b/DSView/main.cpp
@@ -147,7 +147,8 @@ int main(int argc, char *argv[])
// Initialise the main window
pv::MainWindow w(device_manager, open_file);
- QFile qss(":/stylesheet.qss");
+ //QFile qss(":/stylesheet.qss");
+ QFile qss(":qdarkstyle/style.qss");
qss.open(QFile::ReadOnly);
a.setStyleSheet(qss.readAll());
qss.close();
diff --git a/DSView/pv/data/decode/annotation.cpp b/DSView/pv/data/decode/annotation.cpp
index a474dd90..652dc1b9 100644
--- a/DSView/pv/data/decode/annotation.cpp
+++ b/DSView/pv/data/decode/annotation.cpp
@@ -49,6 +49,12 @@ Annotation::Annotation(const srd_proto_data *const pdata) :
}
}
+Annotation::Annotation()
+{
+ _start_sample = 0;
+ _end_sample = 0;
+}
+
Annotation::~Annotation()
{
_annotations.clear();
diff --git a/DSView/pv/data/decode/annotation.h b/DSView/pv/data/decode/annotation.h
index a2676bd3..9ed39bf9 100644
--- a/DSView/pv/data/decode/annotation.h
+++ b/DSView/pv/data/decode/annotation.h
@@ -35,6 +35,7 @@ class Annotation
{
public:
Annotation(const srd_proto_data *const pdata);
+ Annotation();
~Annotation();
uint64_t start_sample() const;
diff --git a/DSView/pv/data/decode/row.cpp b/DSView/pv/data/decode/row.cpp
index 1c0ee9cc..06ae2987 100644
--- a/DSView/pv/data/decode/row.cpp
+++ b/DSView/pv/data/decode/row.cpp
@@ -68,8 +68,8 @@ const QString Row::title() const
bool Row::operator<(const Row &other) const
{
- return (_decoder < other._decoder) ||
- (_decoder == other._decoder && _row < other._row);
+ return (_decoder->name < other._decoder->name) ||
+ (_decoder->name == other._decoder->name && _row->desc < other._row->desc);
}
} // decode
diff --git a/DSView/pv/data/decode/row.h b/DSView/pv/data/decode/row.h
index 6826c0fc..73324302 100644
--- a/DSView/pv/data/decode/row.h
+++ b/DSView/pv/data/decode/row.h
@@ -46,7 +46,7 @@ public:
const QString title() const;
- bool operator<(const Row &other) const;
+ bool operator<(const Row &other) const;
private:
const srd_decoder *_decoder;
diff --git a/DSView/pv/data/decode/rowdata.cpp b/DSView/pv/data/decode/rowdata.cpp
index 840459a6..1fbd31a5 100644
--- a/DSView/pv/data/decode/rowdata.cpp
+++ b/DSView/pv/data/decode/rowdata.cpp
@@ -23,6 +23,7 @@
#include "rowdata.h"
using std::max;
+using std::min;
using std::vector;
namespace pv {
@@ -30,7 +31,8 @@ namespace data {
namespace decode {
RowData::RowData() :
- _max_annotation(0)
+ _max_annotation(0),
+ _min_annotation(UINT64_MAX)
{
}
@@ -51,6 +53,11 @@ uint64_t RowData::get_max_annotation() const
return _max_annotation;
}
+uint64_t RowData::get_min_annotation() const
+{
+ return _min_annotation;
+}
+
void RowData::get_annotation_subset(
vector &dest,
uint64_t start_sample, uint64_t end_sample) const
@@ -62,10 +69,33 @@ void RowData::get_annotation_subset(
dest.push_back(*i);
}
-void RowData::push_annotation(const Annotation &a)
+bool RowData::push_annotation(const Annotation &a)
{
- _annotations.push_back(a);
- _max_annotation = max(_max_annotation, a.end_sample() - a.start_sample());
+ try {
+ _annotations.push_back(a);
+ _max_annotation = max(_max_annotation, a.end_sample() - a.start_sample());
+ if (a.end_sample() != a.start_sample())
+ _min_annotation = min(_min_annotation, a.end_sample() - a.start_sample());
+ return true;
+ } catch (const std::bad_alloc&) {
+ return false;
+ }
+}
+
+uint64_t RowData::get_annotation_size() const
+{
+ return _annotations.size();
+}
+
+bool RowData::get_annotation(Annotation &ann,
+ uint64_t index) const
+{
+ if (index < _annotations.size()) {
+ ann = _annotations[index];
+ return true;
+ } else {
+ return false;
+ }
}
} // decode
diff --git a/DSView/pv/data/decode/rowdata.h b/DSView/pv/data/decode/rowdata.h
index 03076494..11b88420 100644
--- a/DSView/pv/data/decode/rowdata.h
+++ b/DSView/pv/data/decode/rowdata.h
@@ -39,6 +39,7 @@ public:
uint64_t get_max_sample() const;
uint64_t get_max_annotation() const;
+ uint64_t get_min_annotation() const;
/**
* Extracts sorted annotations between two period into a vector.
*/
@@ -46,10 +47,16 @@ public:
std::vector &dest,
uint64_t start_sample, uint64_t end_sample) const;
- void push_annotation(const Annotation &a);
+ bool push_annotation(const Annotation &a);
+
+ uint64_t get_annotation_size() const;
+
+ bool get_annotation(pv::data::decode::Annotation &ann,
+ uint64_t index) const;
private:
uint64_t _max_annotation;
+ uint64_t _min_annotation;
std::vector _annotations;
};
diff --git a/DSView/pv/data/decodermodel.cpp b/DSView/pv/data/decodermodel.cpp
new file mode 100644
index 00000000..9e2c071f
--- /dev/null
+++ b/DSView/pv/data/decodermodel.cpp
@@ -0,0 +1,108 @@
+/*
+ * This file is part of the DSView project.
+ *
+ * Copyright (C) 2016 Andy Deng
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include
+
+#include
+#include
+
+#include
+#include
+
+#include "decoderstack.h"
+#include "decodermodel.h"
+
+using namespace boost;
+using namespace std;
+
+namespace pv {
+namespace data {
+
+DecoderModel::DecoderModel(QObject *parent)
+ : QAbstractTableModel(parent),
+ _decoder_stack(NULL)
+{
+}
+
+void DecoderModel::setDecoderStack(boost::shared_ptr decoder_stack)
+{
+ beginResetModel();
+ _decoder_stack = decoder_stack;
+ endResetModel();
+}
+
+const boost::shared_ptr& DecoderModel::getDecoderStack() const
+{
+ return _decoder_stack;
+}
+
+int DecoderModel::rowCount(const QModelIndex & /* parent */) const
+{
+ if (_decoder_stack)
+ return _decoder_stack->list_annotation_size();
+ else
+ return 100;
+}
+int DecoderModel::columnCount(const QModelIndex & /* parent */) const
+{
+ if (_decoder_stack)
+ return _decoder_stack->list_rows_size();
+ else
+ return 1;
+}
+
+QVariant DecoderModel::data(const QModelIndex &index, int role) const
+{
+ if (!index.isValid())
+ return QVariant();
+
+ if (role == Qt::TextAlignmentRole) {
+ return int(Qt::AlignLeft | Qt::AlignVCenter);
+ } else if (role == Qt::DisplayRole) {
+ if (_decoder_stack) {
+ pv::data::decode::Annotation ann;
+ if (_decoder_stack->list_annotation(ann, index.column(), index.row())) {
+ return ann.annotations().at(0);
+ }
+ }
+ }
+ return QVariant();
+}
+
+QVariant DecoderModel::headerData(int section,
+ Qt::Orientation orientation,
+ int role) const
+{
+ if (role != Qt::DisplayRole)
+ return QVariant();
+
+ if (orientation == Qt::Vertical)
+ return section;
+
+ if (_decoder_stack) {
+ QString title;
+ if (_decoder_stack->list_row_title(section, title))
+ return title;
+ }
+ return QVariant();
+}
+
+} // namespace data
+} // namespace pv
diff --git a/DSView/pv/data/decodermodel.h b/DSView/pv/data/decodermodel.h
new file mode 100644
index 00000000..a0eac14b
--- /dev/null
+++ b/DSView/pv/data/decodermodel.h
@@ -0,0 +1,62 @@
+/*
+ * This file is part of the DSView project.
+ *
+ * Copyright (C) 2016 Andy Deng
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef DSVIEW_PV_DATA_DECODERMODEL_H
+#define DSVIEW_PV_DATA_DECODERMODEL_H
+
+#include
+
+#include
+
+#include
+
+namespace pv {
+namespace data {
+
+class DecoderStack;
+
+namespace decode {
+class Annotation;
+class Decoder;
+class Row;
+}
+
+class DecoderModel : public QAbstractTableModel
+{
+public:
+ DecoderModel(QObject *parent = 0);
+
+ int rowCount(const QModelIndex &parent) const;
+ int columnCount(const QModelIndex &parent) const;
+ QVariant data(const QModelIndex &index, int role) const;
+ QVariant headerData(int section, Qt::Orientation orientation,
+ int role) const;
+
+ void setDecoderStack(boost::shared_ptr decoder_stack);
+ const boost::shared_ptr& getDecoderStack() const;
+
+private:
+ boost::shared_ptr _decoder_stack;
+};
+
+} // namespace data
+} // namespace pv
+
+#endif // DSVIEW_PV_DATA_DECODERMODEL_H
diff --git a/DSView/pv/data/decoderstack.cpp b/DSView/pv/data/decoderstack.cpp
index ed720090..e52a91f4 100644
--- a/DSView/pv/data/decoderstack.cpp
+++ b/DSView/pv/data/decoderstack.cpp
@@ -68,7 +68,8 @@ DecoderStack::DecoderStack(pv::SigSession &session,
_frame_complete(false),
_samples_decoded(0),
_decode_state(Stopped),
- _options_changed(false)
+ _options_changed(false),
+ _no_memory(false)
{
connect(&_session, SIGNAL(frame_began()),
this, SLOT(on_new_frame()));
@@ -79,6 +80,8 @@ DecoderStack::DecoderStack(pv::SigSession &session,
_stack.push_back(shared_ptr(
new decode::Decoder(dec)));
+
+ build_row();
}
DecoderStack::~DecoderStack()
@@ -89,7 +92,10 @@ DecoderStack::~DecoderStack()
// }
stop_decode();
_stack.clear();
- clear();
+ _rows.clear();
+ _rows_gshow.clear();
+ _rows_lshow.clear();
+ _class_rows.clear();
}
const std::list< boost::shared_ptr >&
@@ -102,20 +108,83 @@ void DecoderStack::push(boost::shared_ptr decoder)
{
assert(decoder);
_stack.push_back(decoder);
+ build_row();
+ _options_changed = true;
}
-void DecoderStack::remove(int index)
+void DecoderStack::remove(boost::shared_ptr &decoder)
{
- assert(index >= 0);
- assert(index < (int)_stack.size());
-
// Find the decoder in the stack
list< shared_ptr >::iterator iter = _stack.begin();
- for(int i = 0; i < index; i++, iter++)
- assert(iter != _stack.end());
+ for(int i = 0; i < _stack.size(); i++, iter++)
+ if ((*iter) == decoder)
+ break;
// Delete the element
- _stack.erase(iter);
+ if (iter != _stack.end())
+ _stack.erase(iter);
+
+ build_row();
+ _options_changed = true;
+}
+
+void DecoderStack::build_row()
+{
+ _rows.clear();
+ // Add classes
+ BOOST_FOREACH (const shared_ptr &dec, _stack)
+ {
+ assert(dec);
+ const srd_decoder *const decc = dec->decoder();
+ assert(dec->decoder());
+
+ // Add a row for the decoder if it doesn't have a row list
+ if (!decc->annotation_rows) {
+ const Row row(decc);
+ _rows[row] = decode::RowData();
+ std::map::const_iterator iter = _rows_gshow.find(row);
+ if (iter == _rows_gshow.end()) {
+ if (row.title().contains("bit", Qt::CaseInsensitive) ||
+ row.title().contains("warning", Qt::CaseInsensitive)) {
+ _rows_gshow[row] = false;
+ _rows_lshow[row] = false;
+ } else {
+ _rows_gshow[row] = true;
+ _rows_lshow[row] = true;
+ }
+ }
+ }
+
+ // Add the decoder rows
+ for (const GSList *l = decc->annotation_rows; l; l = l->next)
+ {
+ const srd_decoder_annotation_row *const ann_row =
+ (srd_decoder_annotation_row *)l->data;
+ assert(ann_row);
+
+ const Row row(decc, ann_row);
+
+ // Add a new empty row data object
+ _rows[row] = decode::RowData();
+ std::map::const_iterator iter = _rows_gshow.find(row);
+ if (iter == _rows_gshow.end()) {
+ if (row.title().contains("bit", Qt::CaseInsensitive) ||
+ row.title().contains("warning", Qt::CaseInsensitive)) {
+ _rows_gshow[row] = false;
+ _rows_lshow[row] = false;
+ } else {
+ _rows_gshow[row] = true;
+ _rows_lshow[row] = true;
+ }
+ }
+
+ // Map out all the classes
+ for (const GSList *ll = ann_row->ann_classes;
+ ll; ll = ll->next)
+ _class_rows[make_pair(decc,
+ GPOINTER_TO_INT(ll->data))] = row;
+ }
+ }
}
int64_t DecoderStack::samples_decoded() const
@@ -124,36 +193,6 @@ int64_t DecoderStack::samples_decoded() const
return _samples_decoded;
}
-std::vector< std::pair > DecoderStack::get_visible_rows() const
-{
- lock_guard lock(_output_mutex);
-
- std::vector< std::pair > rows;
-
- BOOST_FOREACH (const shared_ptr &dec, _stack)
- {
- assert(dec);
-
- const srd_decoder *const decc = dec->decoder();
- assert(dec->decoder());
-
- // Add a row for the decoder if it doesn't have a row list
- if (!decc->annotation_rows)
- rows.push_back(make_pair(Row(decc), dec->shown()));
-
- // Add the decoder rows
- for (const GSList *l = decc->annotation_rows; l; l = l->next)
- {
- const srd_decoder_annotation_row *const ann_row =
- (srd_decoder_annotation_row *)l->data;
- assert(ann_row);
- rows.push_back(make_pair(Row(decc, ann_row), dec->shown()));
- }
- }
-
- return rows;
-}
-
void DecoderStack::get_annotation_subset(
std::vector &dest,
const Row &row, uint64_t start_sample,
@@ -161,9 +200,9 @@ void DecoderStack::get_annotation_subset(
{
lock_guard lock(_output_mutex);
- std::map::const_iterator iter =
- _rows.find(row);
- if (iter != _rows.end())
+ std::map::const_iterator iter =
+ _rows.find(row);
+ if (iter != _rows.end())
(*iter).second.get_annotation_subset(dest,
start_sample, end_sample);
}
@@ -180,6 +219,44 @@ uint64_t DecoderStack::get_max_annotation(const Row &row)
return 0;
}
+uint64_t DecoderStack::get_min_annotation(const Row &row)
+{
+ lock_guard lock(_output_mutex);
+
+ std::map::const_iterator iter =
+ _rows.find(row);
+ if (iter != _rows.end())
+ return (*iter).second.get_min_annotation();
+
+ return 0;
+}
+
+std::map& DecoderStack::get_rows_gshow()
+{
+ return _rows_gshow;
+}
+
+std::map& DecoderStack::get_rows_lshow()
+{
+ return _rows_lshow;
+}
+
+void DecoderStack::set_rows_gshow(const decode::Row row, bool show)
+{
+ std::map::const_iterator iter = _rows_gshow.find(row);
+ if (iter != _rows_gshow.end()) {
+ _rows_gshow[row] = show;
+ }
+}
+
+void DecoderStack::set_rows_lshow(const decode::Row row, bool show)
+{
+ std::map::const_iterator iter = _rows_lshow.find(row);
+ if (iter != _rows_lshow.end()) {
+ _rows_lshow[row] = show;
+ }
+}
+
bool DecoderStack::has_annotations(const Row &row) const
{
lock_guard lock(_output_mutex);
@@ -195,6 +272,55 @@ bool DecoderStack::has_annotations(const Row &row) const
return false;
}
+uint64_t DecoderStack::list_annotation_size() const
+{
+ uint64_t max_annotation_size = 0;
+ int row = 0;
+ for (map::const_iterator i = _rows.begin();
+ i != _rows.end(); i++) {
+ map::const_iterator iter = _rows_lshow.find((*i).first);
+ if (iter != _rows_lshow.end() && (*iter).second)
+ max_annotation_size = max(max_annotation_size,
+ (*i).second.get_annotation_size());
+ }
+
+ return max_annotation_size;
+}
+
+bool DecoderStack::list_annotation(pv::data::decode::Annotation &ann,
+ uint16_t row_index, uint64_t col_index) const
+{
+ int row = 0;
+ for (map::const_iterator i = _rows.begin();
+ i != _rows.end(); i++) {
+ map::const_iterator iter = _rows_lshow.find((*i).first);
+ if (iter != _rows_lshow.end() && (*iter).second) {
+ if (row_index-- == 0) {
+ return (*i).second.get_annotation(ann, col_index);
+ }
+ }
+ }
+
+ return false;
+}
+
+
+bool DecoderStack::list_row_title(int row, QString &title) const
+{
+ int index = 0;
+ for (map::const_iterator i = _rows.begin();
+ i != _rows.end(); i++) {
+ map::const_iterator iter = _rows_lshow.find((*i).first);
+ if (iter != _rows_lshow.end() && (*iter).second) {
+ if (row-- == 0) {
+ title = (*i).first.title();
+ return 1;
+ }
+ }
+ }
+ return 0;
+}
+
QString DecoderStack::error_message()
{
lock_guard lock(_output_mutex);
@@ -207,16 +333,20 @@ void DecoderStack::clear()
_frame_complete = false;
_samples_decoded = 0;
_error_message = QString();
- _rows.clear();
- _class_rows.clear();
+ for (map::const_iterator i = _rows.begin();
+ i != _rows.end(); i++)
+ _rows[(*i).first] = decode::RowData();
+ _no_memory = false;
}
void DecoderStack::stop_decode()
{
_snapshot.reset();
- if(_decode_state == Stopped)
+ if(_decode_state == Stopped) {
+ clear();
return;
+ }
if (_decode_thread.get()) {
_decode_thread->interrupt();
@@ -224,6 +354,7 @@ void DecoderStack::stop_decode()
_decode_state = Stopped;
}
_decode_thread.reset();
+ clear();
}
void DecoderStack::begin_decode()
@@ -239,8 +370,6 @@ void DecoderStack::begin_decode()
// }
stop_decode();
- clear();
-
// Check that all decoders have the required channels
BOOST_FOREACH(const shared_ptr &dec, _stack)
if (!dec->have_required_probes()) {
@@ -249,37 +378,6 @@ void DecoderStack::begin_decode()
return;
}
- // Add classes
- BOOST_FOREACH (const shared_ptr &dec, _stack)
- {
- assert(dec);
- const srd_decoder *const decc = dec->decoder();
- assert(dec->decoder());
-
- // Add a row for the decoder if it doesn't have a row list
- if (!decc->annotation_rows)
- _rows[Row(decc)] = decode::RowData();
-
- // Add the decoder rows
- for (const GSList *l = decc->annotation_rows; l; l = l->next)
- {
- const srd_decoder_annotation_row *const ann_row =
- (srd_decoder_annotation_row *)l->data;
- assert(ann_row);
-
- const Row row(decc, ann_row);
-
- // Add a new empty row data object
- _rows[row] = decode::RowData();
-
- // Map out all the classes
- for (const GSList *ll = ann_row->ann_classes;
- ll; ll = ll->next)
- _class_rows[make_pair(decc,
- GPOINTER_TO_INT(ll->data))] = row;
- }
- }
-
// We get the logic data of the first channel in the list.
// This works because we are currently assuming all
// LogicSignals have the same data/snapshot
@@ -313,8 +411,8 @@ uint64_t DecoderStack::get_max_sample_count() const
{
uint64_t max_sample_count = 0;
- for (map::const_iterator i = _rows.begin();
- i != _rows.end(); i++)
+ for (map::const_iterator i = _rows.begin();
+ i != _rows.end(); i++)
max_sample_count = max(max_sample_count,
(*i).second.get_max_sample());
@@ -333,48 +431,6 @@ boost::optional DecoderStack::wait_for_data() const
_sample_count);
}
-//void DecoderStack::decode_data(
-// const uint64_t sample_count, const unsigned int unit_size,
-// srd_session *const session)
-//{
-// //uint8_t chunk[DecodeChunkLength];
-// uint8_t *chunk = NULL;
-// //chunk = (uint8_t *)realloc(chunk, DecodeChunkLength);
-
-// const uint64_t chunk_sample_count =
-// DecodeChunkLength / _snapshot->unit_size();
-
-// for (uint64_t i = 0;
-// !boost::this_thread::interruption_requested() &&
-// i < sample_count;
-// i += chunk_sample_count)
-// {
-// //lock_guard decode_lock(_global_decode_mutex);
-
-// const uint64_t chunk_end = min(
-// i + chunk_sample_count, sample_count);
-// chunk = _snapshot->get_samples(i, chunk_end);
-
-// if (srd_session_send(session, i, i + sample_count, chunk,
-// (chunk_end - i) * unit_size, unit_size) != SRD_OK) {
-// _error_message = tr("Decoder reported an error");
-// break;
-// }
-
-// {
-// lock_guard lock(_output_mutex);
-// _samples_decoded = chunk_end;
-// }
-
-// if (i % DecodeNotifyPeriod == 0)
-// new_decode_data();
-
-// }
-// _options_changed = false;
-// decode_done();
-// //new_decode_data();
-//}
-
void DecoderStack::decode_data(
const uint64_t decode_start, const uint64_t decode_end,
const unsigned int unit_size, srd_session *const session)
@@ -386,7 +442,7 @@ void DecoderStack::decode_data(
for (uint64_t i = decode_start;
!boost::this_thread::interruption_requested() &&
- i < decode_end;
+ i < decode_end && !_no_memory;
i += chunk_sample_count)
{
//lock_guard decode_lock(_global_decode_mutex);
@@ -490,6 +546,11 @@ uint64_t DecoderStack::sample_count() const
return 0;
}
+uint64_t DecoderStack::sample_rate() const
+{
+ return _samplerate;
+}
+
void DecoderStack::annotation_callback(srd_proto_data *pdata, void *decoder)
{
assert(pdata);
@@ -500,6 +561,9 @@ void DecoderStack::annotation_callback(srd_proto_data *pdata, void *decoder)
lock_guard lock(d->_output_mutex);
+ if (d->_no_memory)
+ return;
+
const Annotation a(pdata);
// Find the row
@@ -508,21 +572,21 @@ void DecoderStack::annotation_callback(srd_proto_data *pdata, void *decoder)
const srd_decoder *const decc = pdata->pdo->di->decoder;
assert(decc);
- map::iterator row_iter = d->_rows.end();
+ map::iterator row_iter = d->_rows.end();
// Try looking up the sub-row of this class
const map, Row>::const_iterator r =
d->_class_rows.find(make_pair(decc, a.format()));
if (r != d->_class_rows.end())
- row_iter = d->_rows.find((*r).second);
+ row_iter = d->_rows.find((*r).second);
else
{
// Failing that, use the decoder as a key
- row_iter = d->_rows.find(Row(decc));
+ row_iter = d->_rows.find(Row(decc));
}
- assert(row_iter != d->_rows.end());
- if (row_iter == d->_rows.end()) {
+ assert(row_iter != d->_rows.end());
+ if (row_iter == d->_rows.end()) {
qDebug() << "Unexpected annotation: decoder = " << decc <<
", format = " << a.format();
assert(0);
@@ -530,7 +594,8 @@ void DecoderStack::annotation_callback(srd_proto_data *pdata, void *decoder)
}
// Add the annotation
- (*row_iter).second.push_annotation(a);
+ if (!(*row_iter).second.push_annotation(a))
+ d->_no_memory = true;
}
void DecoderStack::on_new_frame()
@@ -560,21 +625,25 @@ void DecoderStack::on_frame_ended()
begin_decode();
}
-int DecoderStack::cur_rows_size()
+int DecoderStack::list_rows_size()
{
int rows_size = 0;
+ int row = 0;
for (map::const_iterator i = _rows.begin();
- i != _rows.end(); i++)
- if ((*i).second.get_max_sample() != 0)
+ i != _rows.end(); i++) {
+ map::const_iterator iter = _rows_lshow.find((*i).first);
+ if (iter != _rows_lshow.end() && (*iter).second)
rows_size++;
-
- if (rows_size == 0)
- return 1;
- else
- return rows_size;
+ }
+ return rows_size;
}
-void DecoderStack::options_changed(bool changed)
+bool DecoderStack::options_changed() const
+{
+ return _options_changed;
+}
+
+void DecoderStack::set_options_changed(bool changed)
{
_options_changed = changed;
}
diff --git a/DSView/pv/data/decoderstack.h b/DSView/pv/data/decoderstack.h
index 0e71dd52..a60d85dc 100644
--- a/DSView/pv/data/decoderstack.h
+++ b/DSView/pv/data/decoderstack.h
@@ -86,14 +86,13 @@ public:
virtual ~DecoderStack();
- const std::list< boost::shared_ptr >& stack() const;
+ const std::list< boost::shared_ptr >& stack() const;
void push(boost::shared_ptr decoder);
- void remove(int index);
+ void remove(boost::shared_ptr& decoder);
+ void build_row();
int64_t samples_decoded() const;
- std::vector< std::pair > get_visible_rows() const;
-
/**
* Extracts sorted annotations between two period into a vector.
*/
@@ -103,9 +102,23 @@ public:
uint64_t end_sample) const;
uint64_t get_max_annotation(const decode::Row &row);
+ uint64_t get_min_annotation(const decode::Row &row); // except instant(end=start) annotation
+
+ std::map &get_rows_gshow();
+ std::map &get_rows_lshow();
+ void set_rows_gshow(const decode::Row row, bool show);
+ void set_rows_lshow(const decode::Row row, bool show);
bool has_annotations(const decode::Row &row) const;
+ uint64_t list_annotation_size() const;
+
+ bool list_annotation(decode::Annotation &ann,
+ uint16_t row_index, uint64_t col_index) const;
+
+
+ bool list_row_title(int row, QString &title) const;
+
QString error_message();
void clear();
@@ -116,11 +129,13 @@ public:
void stop_decode();
- int cur_rows_size();
+ int list_rows_size();
- void options_changed(bool changed);
+ bool options_changed() const;
+ void set_options_changed(bool changed);
uint64_t sample_count() const;
+ uint64_t sample_rate() const;
private:
boost::optional wait_for_data() const;
@@ -170,9 +185,10 @@ private:
mutable boost::mutex _output_mutex;
int64_t _samples_decoded;
- std::map _rows;
-
- std::map, decode::Row> _class_rows;
+ std::map _rows;
+ std::map _rows_gshow;
+ std::map _rows_lshow;
+ std::map, decode::Row> _class_rows;
QString _error_message;
@@ -180,6 +196,7 @@ private:
decode_state _decode_state;
bool _options_changed;
+ bool _no_memory;
friend class DecoderStackTest::TwoDecoderStack;
};
diff --git a/DSView/pv/dialogs/protocolexp.cpp b/DSView/pv/dialogs/protocolexp.cpp
new file mode 100644
index 00000000..c3baf6bb
--- /dev/null
+++ b/DSView/pv/dialogs/protocolexp.cpp
@@ -0,0 +1,215 @@
+/*
+ * This file is part of the DSView project.
+ * DSView is based on PulseView.
+ *
+ * Copyright (C) 2012 Joel Holdsworth
+ * Copyright (C) 2013 DreamSourceLab
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+
+#include "protocolexp.h"
+
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "../sigsession.h"
+#include "../data/decoderstack.h"
+#include "../data/decode/row.h"
+#include "../data/decode/annotation.h"
+#include "../view/decodetrace.h"
+#include "../data/decodermodel.h"
+
+using namespace boost;
+using namespace std;
+
+namespace pv {
+namespace dialogs {
+
+ProtocolExp::ProtocolExp(QWidget *parent, SigSession &session) :
+ QDialog(parent),
+ _session(session),
+ _button_box(QDialogButtonBox::Ok | QDialogButtonBox::Cancel,
+ Qt::Horizontal, this),
+ _export_cancel(false)
+{
+ _format_combobox = new QComboBox(this);
+ _format_combobox->addItem(tr("Comma-Separated Values (*.csv)"));
+ _format_combobox->addItem(tr("Text files (*.txt)"));
+
+ _flayout = new QFormLayout();
+ _flayout->addRow(new QLabel(tr("Export Format: "), this), _format_combobox);
+
+ pv::data::DecoderModel* decoder_model = _session.get_decoder_model();
+ const boost::shared_ptr& decoder_stack = decoder_model->getDecoderStack();
+ if (decoder_stack) {
+ int row_index = 0;
+ const std::map& rows(decoder_stack->get_rows_lshow());
+ for (std::map::const_iterator i = rows.begin();
+ i != rows.end(); i++) {
+ if ((*i).second) {
+ QLabel *row_label = new QLabel((*i).first.title(), this);
+ QRadioButton *row_sel = new QRadioButton(this);
+ if (row_index == 0) {
+ row_sel->setChecked(true);
+ }
+ _row_label_list.push_back(row_label);
+ _row_sel_list.push_back(row_sel);
+ _flayout->addRow(row_label, row_sel);
+ row_sel->setProperty("index", row_index);
+ row_sel->setProperty("title", (*i).first.title());
+ row_index++;
+ }
+ }
+ }
+
+ _layout = new QVBoxLayout(this);
+ _layout->addLayout(_flayout);
+ _layout->addWidget(&_button_box);
+ setLayout(_layout);
+
+ connect(&_button_box, SIGNAL(accepted()), this, SLOT(accept()));
+ connect(&_button_box, SIGNAL(rejected()), this, SLOT(reject()));
+}
+
+void ProtocolExp::accept()
+{
+ using namespace Qt;
+ using namespace pv::data::decode;
+
+ QDialog::accept();
+
+ if (!_row_sel_list.empty()) {
+ QList supportedFormats;
+ for (int i = _format_combobox->count() - 1; i >= 0; i--) {
+ supportedFormats.push_back(_format_combobox->itemText(i));
+ }
+ QString filter;
+ for(int i = 0; i < supportedFormats.count();i++){
+ filter.append(supportedFormats[i]);
+ if(i < supportedFormats.count() - 1)
+ filter.append(";;");
+ }
+ QString default_filter = _format_combobox->currentText();
+ QString file_name = QFileDialog::getSaveFileName(
+ this, tr("Export Data"), "",filter,&default_filter);
+ if (!file_name.isEmpty()) {
+ QFileInfo f(file_name);
+ QStringList list = default_filter.split('.').last().split(')');
+ QString ext = list.first();
+ if(f.suffix().compare(ext))
+ file_name+=tr(".")+ext;
+
+ QFile file(file_name);
+ file.open(QIODevice::WriteOnly | QIODevice::Text);
+ QTextStream out(&file);
+ out.setCodec("UTF-8");
+ out.setGenerateByteOrderMark(true);
+
+ QFuture future;
+ future = QtConcurrent::run([&]{
+ _export_cancel = false;
+ QString title;
+ int index;
+ for (std::list::const_iterator i = _row_sel_list.begin();
+ i != _row_sel_list.end(); i++) {
+ if ((*i)->isChecked()) {
+ title = (*i)->property("title").toString();
+ index = (*i)->property("index").toULongLong();
+ break;
+ }
+ }
+ out << QString("%1;%2;%3\n")
+ .arg("ID")
+ .arg("Time[s]")
+ .arg(title);
+
+ pv::data::DecoderModel* decoder_model = _session.get_decoder_model();
+ const boost::shared_ptr& decoder_stack = decoder_model->getDecoderStack();
+ int row_index = 0;
+ Row row;
+ const std::map& rows_lshow(decoder_stack->get_rows_lshow());
+ for (std::map::const_iterator i = rows_lshow.begin();
+ i != rows_lshow.end(); i++) {
+ if ((*i).second) {
+ if (index == row_index) {
+ row = (*i).first;
+ break;
+ }
+ row_index++;
+ }
+ }
+
+ uint64_t exported = 0;
+ double time_pre_samples = 1.0 / decoder_stack->samplerate();
+ vector annotations;
+ decoder_stack->get_annotation_subset(annotations, row,
+ 0, decoder_stack->sample_count()-1);
+ if (!annotations.empty()) {
+ BOOST_FOREACH(const Annotation &a, annotations) {
+ out << QString("%1;%2;%3\n")
+ .arg(QString::number(exported))
+ .arg(QString::number(a.start_sample()*time_pre_samples))
+ .arg(a.annotations().at(0));
+ exported++;
+ emit export_progress(exported*100/annotations.size());
+ if (_export_cancel)
+ break;
+ }
+ }
+ });
+ Qt::WindowFlags flags = Qt::CustomizeWindowHint;
+ QProgressDialog dlg(tr("Export Protocol List Result... It can take a while."),
+ tr("Cancel"),0,100,this,flags);
+ dlg.setWindowModality(Qt::WindowModal);
+ dlg.setWindowFlags(Qt::Dialog | Qt::FramelessWindowHint);
+
+ QFutureWatcher watcher;
+ connect(&watcher,SIGNAL(finished()),&dlg,SLOT(cancel()));
+ connect(this,SIGNAL(export_progress(int)),&dlg,SLOT(setValue(int)));
+ connect(&dlg,SIGNAL(canceled()),this,SLOT(cancel_export()));
+ watcher.setFuture(future);
+ dlg.exec();
+
+ future.waitForFinished();
+ file.close();
+ }
+ }
+}
+
+void ProtocolExp::reject()
+{
+ using namespace Qt;
+
+ QDialog::reject();
+}
+
+void ProtocolExp::cancel_export()
+{
+ _export_cancel = true;
+}
+
+} // namespace dialogs
+} // namespace pv
diff --git a/DSView/pv/dialogs/protocolexp.h b/DSView/pv/dialogs/protocolexp.h
new file mode 100644
index 00000000..c793a75c
--- /dev/null
+++ b/DSView/pv/dialogs/protocolexp.h
@@ -0,0 +1,85 @@
+/*
+ * This file is part of the DSView project.
+ * DSView is based on PulseView.
+ *
+ * Copyright (C) 2012 Joel Holdsworth
+ * Copyright (C) 2013 DreamSourceLab
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+
+#ifndef DSVIEW_PV_PROTOCOLEXP_H
+#define DSVIEW_PV_PROTOCOLEXP_H
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+
+#include "../device/devinst.h"
+#include "../prop/binding/deviceoptions.h"
+
+namespace pv {
+
+class SigSession;
+
+namespace data {
+namespace decode {
+class Row;
+}
+}
+
+namespace dialogs {
+
+class ProtocolExp : public QDialog
+{
+ Q_OBJECT
+
+public:
+ ProtocolExp(QWidget *parent, SigSession &session);
+
+protected:
+ void accept();
+ void reject();
+
+signals:
+ void export_progress(int percent);
+
+private slots:
+ void cancel_export();
+
+private:
+ SigSession &_session;
+
+ QComboBox *_format_combobox;
+ std::list _row_sel_list;
+ std::list _row_label_list;
+ QFormLayout *_flayout;
+ QVBoxLayout *_layout;
+ QDialogButtonBox _button_box;
+
+ bool _export_cancel;
+};
+
+} // namespace dialogs
+} // namespace pv
+
+#endif // DSVIEW_PV_PROTOCOLEXP_H
diff --git a/DSView/pv/dialogs/protocollist.cpp b/DSView/pv/dialogs/protocollist.cpp
new file mode 100644
index 00000000..6f6e090c
--- /dev/null
+++ b/DSView/pv/dialogs/protocollist.cpp
@@ -0,0 +1,183 @@
+/*
+ * This file is part of the DSView project.
+ * DSView is based on PulseView.
+ *
+ * Copyright (C) 2012 Joel Holdsworth
+ * Copyright (C) 2013 DreamSourceLab
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+
+#include "protocollist.h"
+
+#include
+
+#include
+#include
+#include
+
+#include "../sigsession.h"
+#include "../data/decoderstack.h"
+#include "../data/decode/row.h"
+#include "../view/decodetrace.h"
+#include "../data/decodermodel.h"
+
+using namespace boost;
+using namespace std;
+
+namespace pv {
+namespace dialogs {
+
+ProtocolList::ProtocolList(QWidget *parent, SigSession &session) :
+ QDialog(parent),
+ _session(session),
+ _button_box(QDialogButtonBox::Ok,
+ Qt::Horizontal, this)
+{
+ pv::data::DecoderModel* decoder_model = _session.get_decoder_model();
+
+
+ _protocol_combobox = new QComboBox(this);
+ const std::vector< boost::shared_ptr > decode_sigs(
+ _session.get_decode_signals());
+ int index = 0;
+ BOOST_FOREACH(boost::shared_ptr d, decode_sigs) {
+ _protocol_combobox->addItem(d->get_name());
+ if (decoder_model->getDecoderStack() == d->decoder())
+ _protocol_combobox->setCurrentIndex(index);
+ index++;
+ }
+ _protocol_combobox->addItem("", qVariantFromValue(NULL));
+ if (decoder_model->getDecoderStack() == NULL)
+ _protocol_combobox->setCurrentIndex(index);
+
+ _flayout = new QFormLayout();
+ _flayout->addRow(new QLabel(tr("Decoded Protocols: "), this), _protocol_combobox);
+
+ _layout = new QVBoxLayout(this);
+ _layout->addLayout(_flayout);
+ _layout->addWidget(&_button_box);
+ setLayout(_layout);
+
+ connect(&_button_box, SIGNAL(accepted()), this, SLOT(accept()));
+ connect(_protocol_combobox, SIGNAL(currentIndexChanged(int)), this, SLOT(set_protocol(int)));
+ set_protocol(_protocol_combobox->currentIndex());
+}
+
+void ProtocolList::accept()
+{
+ using namespace Qt;
+
+ QDialog::accept();
+}
+
+void ProtocolList::reject()
+{
+ using namespace Qt;
+
+ QDialog::accept();
+}
+
+void ProtocolList::set_protocol(int index)
+{
+ (void)index;
+
+ for(std::list::const_iterator i = _show_checkbox_list.begin();
+ i != _show_checkbox_list.end(); i++) {
+ (*i)->setParent(NULL);
+ _flayout->removeWidget((*i));
+ delete (*i);
+ }
+ _show_checkbox_list.clear();
+ for(std::list::const_iterator i = _show_label_list.begin();
+ i != _show_label_list.end(); i++) {
+ (*i)->setParent(NULL);
+ _flayout->removeWidget((*i));
+ delete (*i);
+ }
+ _show_label_list.clear();
+
+ boost::shared_ptr decoder_stack;
+ const std::vector< boost::shared_ptr > decode_sigs(
+ _session.get_decode_signals());
+ int cur_index = 0;
+ BOOST_FOREACH(boost::shared_ptr d, decode_sigs) {
+ if (index == cur_index) {
+ decoder_stack = d->decoder();
+ break;
+ }
+ cur_index++;
+ }
+
+ if (!decoder_stack){
+ _session.get_decoder_model()->setDecoderStack(NULL);
+ return;
+ }
+
+ _session.get_decoder_model()->setDecoderStack(decoder_stack);
+ int row_index = 0;
+ const std::map& rows(decoder_stack->get_rows_lshow());
+ for (std::map::const_iterator i = rows.begin();
+ i != rows.end(); i++) {
+ QLabel *row_label = new QLabel((*i).first.title(), this);
+ QCheckBox *row_checkbox = new QCheckBox(this);
+ //row_checkbox->setChecked(false);
+ _show_label_list.push_back(row_label);
+ _show_checkbox_list.push_back(row_checkbox);
+ _flayout->addRow(row_label, row_checkbox);
+
+ row_checkbox->setChecked((*i).second);
+ connect(row_checkbox, SIGNAL(clicked(bool)), this, SLOT(on_row_check(bool)));
+ row_checkbox->setProperty("index", row_index);
+ row_index++;
+ }
+}
+
+void ProtocolList::on_row_check(bool show)
+{
+ QCheckBox *sc = dynamic_cast(sender());
+ QVariant id = sc->property("index");
+ int index = id.toInt();
+
+ boost::shared_ptr decoder_stack;
+ const std::vector< boost::shared_ptr > decode_sigs(
+ _session.get_decode_signals());
+ int cur_index = 0;
+ BOOST_FOREACH(boost::shared_ptr d, decode_sigs) {
+ if (cur_index == _protocol_combobox->currentIndex()) {
+ decoder_stack = d->decoder();
+ break;
+ }
+ cur_index++;
+ }
+
+ if (!decoder_stack)
+ return;
+
+ std::map& rows(decoder_stack->get_rows_lshow());
+ for (std::map::const_iterator i = rows.begin();
+ i != rows.end(); i++) {
+ if (index-- == 0) {
+ decoder_stack->set_rows_lshow((*i).first, show);
+ break;
+ }
+ }
+
+ _session.get_decoder_model()->setDecoderStack(decoder_stack);
+}
+
+} // namespace dialogs
+} // namespace pv
diff --git a/DSView/pv/dialogs/protocollist.h b/DSView/pv/dialogs/protocollist.h
new file mode 100644
index 00000000..6d315322
--- /dev/null
+++ b/DSView/pv/dialogs/protocollist.h
@@ -0,0 +1,76 @@
+/*
+ * This file is part of the DSView project.
+ * DSView is based on PulseView.
+ *
+ * Copyright (C) 2012 Joel Holdsworth
+ * Copyright (C) 2013 DreamSourceLab
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+
+#ifndef DSVIEW_PV_PROTOCOLLIST_H
+#define DSVIEW_PV_PROTOCOLLIST_H
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+
+#include "../device/devinst.h"
+#include "../prop/binding/deviceoptions.h"
+
+namespace pv {
+
+class SigSession;
+
+namespace dialogs {
+
+class ProtocolList : public QDialog
+{
+ Q_OBJECT
+
+public:
+ ProtocolList(QWidget *parent, SigSession &session);
+
+protected:
+ void accept();
+ void reject();
+
+private slots:
+ void set_protocol(int index);
+ void on_row_check(bool show);
+
+private:
+ SigSession &_session;
+
+ QComboBox *_protocol_combobox;
+ std::list _show_checkbox_list;
+ std::list _show_label_list;
+ QFormLayout *_flayout;
+ QVBoxLayout *_layout;
+ QDialogButtonBox _button_box;
+
+};
+
+} // namespace dialogs
+} // namespace pv
+
+#endif // DSVIEW_PV_PROTOCOLLIST_H
diff --git a/DSView/pv/dock/protocoldock.cpp b/DSView/pv/dock/protocoldock.cpp
index 7756af9e..637022e1 100644
--- a/DSView/pv/dock/protocoldock.cpp
+++ b/DSView/pv/dock/protocoldock.cpp
@@ -25,13 +25,21 @@
#include "../sigsession.h"
#include "../view/decodetrace.h"
#include "../device/devinst.h"
+#include "../data/decodermodel.h"
+#include "../data/decoderstack.h"
+#include "../dialogs/protocollist.h"
+#include "../dialogs/protocolexp.h"
#include
#include
#include
#include
#include
+#include
+#include
+#include
+#include
#include
namespace pv {
@@ -41,20 +49,20 @@ ProtocolDock::ProtocolDock(QWidget *parent, SigSession &session) :
QScrollArea(parent),
_session(session)
{
- _widget = new QWidget(this);
+ _up_widget = new QWidget(this);
QHBoxLayout *hori_layout = new QHBoxLayout();
- _add_button = new QPushButton(_widget);
+ _add_button = new QPushButton(_up_widget);
_add_button->setFlat(true);
_add_button->setIcon(QIcon::fromTheme("protocol",
QIcon(":/icons/add.png")));
- _del_all_button = new QPushButton(_widget);
+ _del_all_button = new QPushButton(_up_widget);
_del_all_button->setFlat(true);
_del_all_button->setIcon(QIcon::fromTheme("protocol",
QIcon(":/icons/del.png")));
_del_all_button->setCheckable(true);
- _protocol_combobox = new QComboBox(_widget);
+ _protocol_combobox = new QComboBox(_up_widget);
GSList *l = g_slist_sort(g_slist_copy(
(GSList*)srd_decoder_list()), decoder_name_cmp);
@@ -80,15 +88,72 @@ ProtocolDock::ProtocolDock(QWidget *parent, SigSession &session) :
connect(_del_all_button, SIGNAL(clicked()),
this, SLOT(del_protocol()));
- _layout = new QVBoxLayout();
- _layout->addLayout(hori_layout);
- _layout->addStretch(1);
+ _up_layout = new QVBoxLayout();
+ _up_layout->addLayout(hori_layout);
+ _up_layout->addStretch(1);
- _widget->setLayout(_layout);
+ _up_widget->setLayout(_up_layout);
+ _up_widget->setMinimumHeight(120);
- this->setWidget(_widget);
- _widget->setGeometry(0, 0, sizeHint().width(), 500);
- _widget->setObjectName("protocolWidget");
+// this->setWidget(_widget);
+// _widget->setGeometry(0, 0, sizeHint().width(), 500);
+// _widget->setObjectName("protocolWidget");
+
+ _dn_widget = new QWidget(this);
+
+ _dn_set_button = new QPushButton(_dn_widget);
+ _dn_set_button->setFlat(true);
+ _dn_set_button->setIcon(QIcon::fromTheme("protocol",
+ QIcon(":/icons/gear.png")));
+ connect(_dn_set_button, SIGNAL(clicked()),
+ this, SLOT(set_model()));
+
+ _dn_save_button = new QPushButton(_dn_widget);
+ _dn_save_button->setFlat(true);
+ _dn_save_button->setIcon(QIcon::fromTheme("protocol",
+ QIcon(":/icons/save.png")));
+ connect(_dn_save_button, SIGNAL(clicked()),
+ this, SLOT(export_table_view()));
+
+ QHBoxLayout *dn_title_layout = new QHBoxLayout();
+ dn_title_layout->addWidget(_dn_set_button, 0, Qt::AlignLeft);
+ dn_title_layout->addWidget(_dn_save_button, 0, Qt::AlignLeft);
+ dn_title_layout->addWidget(new QLabel(tr("Protocol List Viewer"), _dn_widget), 1, Qt::AlignLeft);
+ dn_title_layout->addStretch(1);
+
+ _table_view = new QTableView(_dn_widget);
+ _table_view->setModel(_session.get_decoder_model());
+ _table_view->setAlternatingRowColors(true);
+ _table_view->setShowGrid(false);
+ _table_view->horizontalHeader()->setStretchLastSection(true);
+ _table_view->setHorizontalScrollMode(QAbstractItemView::ScrollPerPixel);
+ _table_view->setVerticalScrollMode(QAbstractItemView::ScrollPerPixel);
+
+ QVBoxLayout *dn_layout = new QVBoxLayout();
+ dn_layout->addLayout(dn_title_layout);
+ dn_layout->addWidget(_table_view);
+
+ _dn_widget->setLayout(dn_layout);
+ _dn_widget->setMinimumHeight(400);
+
+ _split_widget = new QSplitter(this);
+ _split_widget->insertWidget(0, _up_widget);
+ _split_widget->insertWidget(1, _dn_widget);
+ _split_widget->setOrientation(Qt::Vertical);
+ _split_widget->setCollapsible(0, false);
+ _split_widget->setCollapsible(1, false);
+ //_split_widget->setStretchFactor(1, 1);
+ //_split_widget
+
+ this->setWidgetResizable(true);
+ this->setWidget(_split_widget);
+ //_split_widget->setGeometry(0, 0, sizeHint().width(), 500);
+ _split_widget->setObjectName("protocolWidget");
+
+ connect(&_session, SIGNAL(decode_done()), this, SLOT(update_model()));
+ connect(this, SIGNAL(protocol_updated()), this, SLOT(update_model()));
+ connect(_table_view, SIGNAL(clicked(QModelIndex)), this, SLOT(item_clicked(QModelIndex)));
+ connect(_table_view->horizontalHeader(), SIGNAL(sectionResized(int,int,int)), this, SLOT(column_resize(int, int, int)));
}
ProtocolDock::~ProtocolDock()
@@ -126,15 +191,15 @@ void ProtocolDock::add_protocol()
//QMap & _options = dlg.get_options();
//QMap _options_index = dlg.get_options_index();
- QPushButton *_del_button = new QPushButton(_widget);
- QPushButton *_set_button = new QPushButton(_widget);
+ QPushButton *_del_button = new QPushButton(_up_widget);
+ QPushButton *_set_button = new QPushButton(_up_widget);
_del_button->setFlat(true);
_del_button->setIcon(QIcon::fromTheme("protocol",
QIcon(":/icons/del.png")));
_set_button->setFlat(true);
_set_button->setIcon(QIcon::fromTheme("protocol",
QIcon(":/icons/gear.png")));
- QLabel *_protocol_label = new QLabel(_widget);
+ QLabel *_protocol_label = new QLabel(_up_widget);
_del_button->setCheckable(true);
_protocol_label->setText(_protocol_combobox->currentText());
@@ -155,9 +220,10 @@ void ProtocolDock::add_protocol()
hori_layout->addWidget(_protocol_label);
hori_layout->addStretch(1);
_hori_layout_list.push_back(hori_layout);
- _layout->insertLayout(_del_button_list.size(), hori_layout);
+ _up_layout->insertLayout(_del_button_list.size(), hori_layout);
//_session.add_protocol_analyzer(_protocol_combobox->currentIndex(), _sel_probes, _options, _options_index);
+ protocol_updated();
}
}
}
@@ -183,6 +249,7 @@ void ProtocolDock::rst_protocol()
}
rst_index++;
}
+ protocol_updated();
}
void ProtocolDock::del_protocol()
@@ -193,7 +260,7 @@ void ProtocolDock::del_protocol()
int del_index = 0;
for (QVector ::const_iterator i = _hori_layout_list.begin();
i != _hori_layout_list.end(); i++) {
- _layout->removeItem((*i));
+ _up_layout->removeItem((*i));
delete (*i);
delete _del_button_list.at(del_index);
delete _set_button_list.at(del_index);
@@ -220,7 +287,7 @@ void ProtocolDock::del_protocol()
for (QVector ::const_iterator i = _del_button_list.begin();
i != _del_button_list.end(); i++) {
if ((*i)->isChecked()) {
- _layout->removeItem(_hori_layout_list.at(del_index));
+ _up_layout->removeItem(_hori_layout_list.at(del_index));
delete _hori_layout_list.at(del_index);
delete _del_button_list.at(del_index);
@@ -234,12 +301,12 @@ void ProtocolDock::del_protocol()
_protocol_index_list.remove(del_index);
_session.remove_decode_signal(del_index);
-
break;
}
del_index++;
}
}
+ protocol_updated();
}
void ProtocolDock::del_all_protocol()
@@ -248,7 +315,7 @@ void ProtocolDock::del_all_protocol()
int del_index = 0;
for (QVector ::const_iterator i = _hori_layout_list.begin();
i != _hori_layout_list.end(); i++) {
- _layout->removeItem((*i));
+ _up_layout->removeItem((*i));
delete (*i);
delete _del_button_list.at(del_index);
delete _set_button_list.at(del_index);
@@ -262,8 +329,90 @@ void ProtocolDock::del_all_protocol()
_set_button_list.clear();
_protocol_label_list.clear();
_protocol_index_list.clear();
+
+ protocol_updated();
}
}
+void ProtocolDock::set_model()
+{
+ pv::dialogs::ProtocolList *protocollist_dlg = new pv::dialogs::ProtocolList(this, _session);
+ protocollist_dlg->exec();
+ resize_table_view(_session.get_decoder_model());
+}
+
+void ProtocolDock::update_model()
+{
+ pv::data::DecoderModel *decoder_model = _session.get_decoder_model();
+ const std::vector< boost::shared_ptr > decode_sigs(
+ _session.get_decode_signals());
+ if (decode_sigs.size() == 0)
+ decoder_model->setDecoderStack(NULL);
+ else if (!decoder_model->getDecoderStack())
+ decoder_model->setDecoderStack(decode_sigs.at(0)->decoder());
+ else {
+ int index = 0;
+ BOOST_FOREACH(const boost::shared_ptr d, decode_sigs) {
+ if (d->decoder() == decoder_model->getDecoderStack()) {
+ decoder_model->setDecoderStack(d->decoder());
+ break;
+ }
+ index++;
+ }
+ if (index >= decode_sigs.size())
+ decoder_model->setDecoderStack(decode_sigs.at(0)->decoder());
+ }
+
+ resize_table_view(decoder_model);
+}
+
+void ProtocolDock::resize_table_view(data::DecoderModel* decoder_model)
+{
+ if (decoder_model->getDecoderStack()) {
+ for (int i = 0; i < decoder_model->columnCount(QModelIndex()) - 1; i++) {
+ _table_view->resizeColumnToContents(i);
+ if (_table_view->columnWidth(i) > 200)
+ _table_view->setColumnWidth(i, 200);
+ }
+ int top_row = _table_view->rowAt(0);
+ int bom_row = _table_view->rowAt(_table_view->height());
+ if (bom_row >= top_row && top_row >= 0) {
+ for (int i = top_row; i <= bom_row; i++)
+ _table_view->resizeRowToContents(i);
+ }
+ }
+}
+
+void ProtocolDock::item_clicked(const QModelIndex &index)
+{
+ pv::data::DecoderModel *decoder_model = _session.get_decoder_model();
+ boost::shared_ptr decoder_stack = decoder_model->getDecoderStack();
+ if (decoder_stack) {
+ pv::data::decode::Annotation ann;
+ if (decoder_stack->list_annotation(ann, index.column(), index.row())) {
+ _session.show_region(ann.start_sample(), ann.end_sample());
+ }
+ }
+}
+
+void ProtocolDock::column_resize(int index, int old_size, int new_size)
+{
+ pv::data::DecoderModel *decoder_model = _session.get_decoder_model();
+ if (decoder_model->getDecoderStack()) {
+ int top_row = _table_view->rowAt(0);
+ int bom_row = _table_view->rowAt(_table_view->height());
+ if (bom_row >= top_row && top_row >= 0) {
+ for (int i = top_row; i <= bom_row; i++)
+ _table_view->resizeRowToContents(i);
+ }
+ }
+}
+
+void ProtocolDock::export_table_view()
+{
+ pv::dialogs::ProtocolExp *protocolexp_dlg = new pv::dialogs::ProtocolExp(this, _session);
+ protocolexp_dlg->exec();
+}
+
} // namespace dock
} // namespace pv
diff --git a/DSView/pv/dock/protocoldock.h b/DSView/pv/dock/protocoldock.h
index 248d1862..96d31124 100644
--- a/DSView/pv/dock/protocoldock.h
+++ b/DSView/pv/dock/protocoldock.h
@@ -34,15 +34,23 @@
#include
#include
#include
+#include
+#include
#include
#include
+#include "../data/decodermodel.h"
+
namespace pv {
class SigSession;
+namespace data {
+class DecoderModel;
+}
+
namespace dock {
class ProtocolDock : public QScrollArea
@@ -58,19 +66,29 @@ public:
void del_all_protocol();
signals:
+ void protocol_updated();
private slots:
void add_protocol();
void rst_protocol();
void del_protocol();
+ void set_model();
+ void update_model();
+ void export_table_view();
+ void item_clicked(const QModelIndex &index);
+ void column_resize(int index, int old_size, int new_size);
private:
static int decoder_name_cmp(const void *a, const void *b);
+ void resize_table_view(data::DecoderModel *decoder_model);
private:
SigSession &_session;
- QWidget *_widget;
+ QSplitter *_split_widget;
+ QWidget *_up_widget;
+ QWidget *_dn_widget;
+ QTableView *_table_view;
QPushButton *_add_button;
QPushButton *_del_all_button;
@@ -80,7 +98,10 @@ private:
QVector _protocol_label_list;
QVector _protocol_index_list;
QVector _hori_layout_list;
- QVBoxLayout *_layout;
+ QVBoxLayout *_up_layout;
+
+ QPushButton *_dn_set_button;
+ QPushButton *_dn_save_button;
};
} // namespace dock
diff --git a/DSView/pv/mainwindow.cpp b/DSView/pv/mainwindow.cpp
index 2b708075..90417108 100644
--- a/DSView/pv/mainwindow.cpp
+++ b/DSView/pv/mainwindow.cpp
@@ -197,7 +197,9 @@ void MainWindow::setup_ui()
SLOT(device_change()));
connect(_dso_trigger_widget, SIGNAL(set_trig_pos(quint64)), _view,
SLOT(set_trig_pos(quint64)));
+ connect(_protocol_widget, SIGNAL(protocol_updated()), _view, SLOT(signals_changed()));
+ setIconSize(QSize(40,40));
addToolBar(_sampling_bar);
addToolBar(_trig_bar);
addToolBar(_file_bar);
diff --git a/DSView/pv/sigsession.cpp b/DSView/pv/sigsession.cpp
index 19bf99f5..8b0802cf 100644
--- a/DSView/pv/sigsession.cpp
+++ b/DSView/pv/sigsession.cpp
@@ -41,6 +41,7 @@
#include "data/groupsnapshot.h"
#include "data/decoderstack.h"
#include "data/decode/decoder.h"
+#include "data/decodermodel.h"
#include "view/analogsignal.h"
#include "view/dsosignal.h"
@@ -99,6 +100,7 @@ SigSession::SigSession(DeviceManager &device_manager) :
_refresh_timer.stop();
_refresh_timer.setSingleShot(true);
_data_lock = false;
+ _decoder_model = new pv::data::DecoderModel(this);
connect(this, SIGNAL(start_timer(int)), &_view_timer, SLOT(start(int)));
//connect(&_view_timer, SIGNAL(timeout()), this, SLOT(refresh()));
connect(&_refresh_timer, SIGNAL(timeout()), this, SLOT(data_unlock()));
@@ -455,7 +457,6 @@ void SigSession::start_capture(bool instant,
_view_timer.blockSignals(false);
// Begin the session
-
_sampling_thread.reset(new boost::thread(
&SigSession::sample_thread_proc, this, _dev_inst,
error_handler));
@@ -1104,9 +1105,10 @@ void SigSession::data_feed_in(const struct sr_dev_inst *sdi,
_cur_logic_snapshot.reset();
_cur_dso_snapshot.reset();
_cur_analog_snapshot.reset();
-
+#ifdef ENABLE_DECODE
BOOST_FOREACH(const boost::shared_ptr d, _decode_traces)
d->frame_ended();
+#endif
}
frame_ended();
@@ -1394,6 +1396,12 @@ void SigSession::rst_decoder(view::DecodeTrace *signal)
return;
}
}
+
+pv::data::DecoderModel* SigSession::get_decoder_model() const
+{
+ return _decoder_model;
+}
+
#endif
} // namespace pv
diff --git a/DSView/pv/sigsession.h b/DSView/pv/sigsession.h
index 23ad6a90..de159f17 100644
--- a/DSView/pv/sigsession.h
+++ b/DSView/pv/sigsession.h
@@ -67,6 +67,7 @@ class Logic;
class LogicSnapshot;
class Group;
class GroupSnapshot;
+class DecoderModel;
}
namespace device {
@@ -154,6 +155,8 @@ public:
void rst_decoder(view::DecodeTrace *signal);
+ pv::data::DecoderModel* get_decoder_model() const;
+
#endif
void init_signals();
@@ -234,6 +237,7 @@ private:
std::vector< boost::shared_ptr > _group_traces;
#ifdef ENABLE_DECODE
std::vector< boost::shared_ptr > _decode_traces;
+ pv::data::DecoderModel *_decoder_model;
#endif
mutable boost::mutex _data_mutex;
@@ -291,6 +295,10 @@ signals:
void zero_adj();
void progressSaveFileValueChanged(int percent);
+ void decode_done();
+
+ void show_region(uint64_t start, uint64_t end);
+
public slots:
void reload();
void refresh(int holdtime);
diff --git a/DSView/pv/toolbars/samplingbar.cpp b/DSView/pv/toolbars/samplingbar.cpp
index 85b45603..ed758736 100644
--- a/DSView/pv/toolbars/samplingbar.cpp
+++ b/DSView/pv/toolbars/samplingbar.cpp
@@ -454,7 +454,8 @@ void SamplingBar::update_sample_rate_selector_value()
break;
}
}
- update_scale();
+ if (samplerate != _sample_rate.itemData(_sample_rate.currentIndex()).value())
+ update_scale();
_updating_sample_rate = false;
}
@@ -511,7 +512,7 @@ void SamplingBar::on_samplecount_sel(int index)
g_variant_new_uint64(sample_count));
sample_count_changed();
- update_scale();
+ //update_scale();
}
}
@@ -535,7 +536,7 @@ void SamplingBar::on_samplerate_sel(int index)
SR_CONF_SAMPLERATE,
g_variant_new_uint64(sample_rate));
- update_scale();
+ //update_scale();
}
}
@@ -625,9 +626,11 @@ void SamplingBar::update_sample_count_selector_value()
i).value())
_sample_count.setCurrentIndex(i);
+ if (samplecount != _sample_count.itemData(_sample_count.currentIndex()).value()) {
+ sample_count_changed();
+ update_scale();
+ }
_updating_sample_count = false;
- sample_count_changed();
- update_scale();
}
void SamplingBar::commit_sample_count()
diff --git a/DSView/pv/view/decodetrace.cpp b/DSView/pv/view/decodetrace.cpp
index a8c84244..bd076af5 100644
--- a/DSView/pv/view/decodetrace.cpp
+++ b/DSView/pv/view/decodetrace.cpp
@@ -125,7 +125,6 @@ DecodeTrace::DecodeTrace(pv::SigSession &session,
_end_index(0),
_start_count(0),
_end_count(0),
- _show_hide_mapper(this),
_popup_form(NULL),
_popup()
{
@@ -137,8 +136,6 @@ DecodeTrace::DecodeTrace(pv::SigSession &session,
this, SLOT(on_new_decode_data()));
connect(_decoder_stack.get(), SIGNAL(decode_done()),
this, SLOT(on_decode_done()));
- connect(&_show_hide_mapper, SIGNAL(mapped(int)),
- this, SLOT(on_show_hide_decoder(int)));
}
DecodeTrace::~DecodeTrace()
@@ -203,7 +200,7 @@ void DecodeTrace::paint_back(QPainter &p, int left, int right)
void DecodeTrace::paint_mid(QPainter &p, int left, int right)
{
- using namespace pv::data::decode;
+ using namespace pv::data::decode;
const double scale = _view->scale();
assert(scale > 0);
@@ -249,47 +246,57 @@ void DecodeTrace::paint_mid(QPainter &p, int left, int right)
const double decode_startX = _decode_start/samples_per_pixel - (_view->offset() / _view->scale());
const double decode_endX = _decode_end/samples_per_pixel - (_view->offset() / _view->scale());
- const std::vector< std::pair > rows(_decoder_stack->get_visible_rows());
- for (size_t i = 0; i < rows.size(); i++)
- {
- const Row &row = rows[i].first;
- const bool shown = rows[i].second;
- if (!shown && _decoder_stack->has_annotations(row)) {
- draw_unshown_row(p, y, annotation_height, decode_startX, decode_endX);
- y += annotation_height;
- _cur_row_headings.push_back(row.title());
- continue;
- }
+ BOOST_FOREACH(boost::shared_ptr dec,
+ _decoder_stack->stack()) {
+ if (dec->shown()) {
+ const std::map& rows(_decoder_stack->get_rows_gshow());
+ for (std::map::const_iterator i = rows.begin();
+ i != rows.end(); i++) {
+ if ((*i).first.decoder() == dec->decoder() &&
+ _decoder_stack->has_annotations((*i).first)) {
+ if ((*i).second) {
+ const Row &row = (*i).first;
+ size_t base_colour = 0x13579BDF;
+ boost::hash_combine(base_colour, this);
+ boost::hash_combine(base_colour, row.decoder());
+ boost::hash_combine(base_colour, row.row());
+ base_colour >>= 16;
- size_t base_colour = 0x13579BDF;
- boost::hash_combine(base_colour, this);
- boost::hash_combine(base_colour, row.decoder());
- boost::hash_combine(base_colour, row.row());
- base_colour >>= 16;
+ const uint64_t min_annotation =
+ _decoder_stack->get_min_annotation(row);
+ const double min_annWidth = min_annotation / samples_per_pixel;
- const uint64_t max_annotation =
- _decoder_stack->get_max_annotation(row);
- const double max_annWidth = max_annotation / samples_per_pixel;
- if (max_annWidth > 5) {
- vector annotations;
- _decoder_stack->get_annotation_subset(annotations, row,
- start_sample, end_sample);
- if (!annotations.empty()) {
- BOOST_FOREACH(const Annotation &a, annotations)
- draw_annotation(a, p, get_text_colour(),
- annotation_height, left, right,
- samples_per_pixel, pixels_offset, y,
- base_colour);
+ const uint64_t max_annotation =
+ _decoder_stack->get_max_annotation(row);
+ const double max_annWidth = max_annotation / samples_per_pixel;
+ if (max_annWidth > 5) {
+ vector annotations;
+ _decoder_stack->get_annotation_subset(annotations, row,
+ start_sample, end_sample);
+ if (!annotations.empty()) {
+ BOOST_FOREACH(const Annotation &a, annotations)
+ draw_annotation(a, p, get_text_colour(),
+ annotation_height, left, right,
+ samples_per_pixel, pixels_offset, y,
+ base_colour, min_annWidth);
+ }
+ } else if (max_annWidth != 0){
+ draw_nodetail(p, annotation_height, left, right, y, base_colour);
+ }
+ if (max_annWidth != 0) {
+ y += annotation_height;
+ _cur_row_headings.push_back(row.title());
+ }
+ }
+ }
}
- } else if (max_annWidth != 0){
- draw_nodetail(p, annotation_height, decode_startX, decode_endX, y, base_colour);
- }
- if (max_annWidth != 0) {
+ } else {
+ draw_unshown_row(p, y, annotation_height, left, right, tr("Unshown"));
y += annotation_height;
- _cur_row_headings.push_back(row.title());
+ _cur_row_headings.push_back(dec->decoder()->name);
}
- }
+ }
}
void DecodeTrace::paint_fore(QPainter &p, int left, int right)
@@ -350,8 +357,8 @@ bool DecodeTrace::create_popup()
BOOST_FOREACH(boost::shared_ptr dec,
_decoder_stack->stack())
{
- if (dec->commit()) {
- _decoder_stack->options_changed(true);
+ if (dec->commit() || _decoder_stack->options_changed()) {
+ _decoder_stack->set_options_changed(true);
_decode_start = dec->decode_start();
_decode_end = dec->decode_end();
ret = true;
@@ -378,6 +385,9 @@ void DecodeTrace::create_popup_form()
_popup_form = new QFormLayout(_popup);
_popup->setLayout(_popup_form);
populate_popup_form(_popup, _popup_form);
+ const int width = _popup_form->sizeHint().width();
+ const int height = _popup_form->sizeHint().height();
+ _popup->resize(width, height);
}
void DecodeTrace::populate_popup_form(QWidget *parent, QFormLayout *form)
@@ -395,20 +405,15 @@ void DecodeTrace::populate_popup_form(QWidget *parent, QFormLayout *form)
const list< boost::shared_ptr >& stack = _decoder_stack->stack();
- if (stack.empty())
- {
+ if (stack.empty()) {
QLabel *const l = new QLabel(
tr("No decoders in the stack
"));
l->setAlignment(Qt::AlignCenter);
form->addRow(l);
- }
- else
- {
- list< boost::shared_ptr >::const_iterator iter =
- stack.begin();
- for (int i = 0; i < (int)stack.size(); i++, iter++) {
- boost::shared_ptr dec(*iter);
- create_decoder_form(i, dec, parent, form);
+ } else {
+ BOOST_FOREACH(boost::shared_ptr dec,stack) {
+ //boost::shared_ptr dec(*iter);
+ create_decoder_form(_decoder_stack, dec, parent, form);
}
form->addRow(new QLabel(
@@ -477,9 +482,9 @@ void DecodeTrace::populate_popup_form(QWidget *parent, QFormLayout *form)
}
void DecodeTrace::draw_annotation(const pv::data::decode::Annotation &a,
- QPainter &p, QColor text_color, int h, int left, int right,
- double samples_per_pixel, double pixels_offset, int y,
- size_t base_colour) const
+ QPainter &p, QColor text_color, int h, int left, int right,
+ double samples_per_pixel, double pixels_offset, int y,
+ size_t base_colour, double min_annWidth) const
{
const double start = max(a.start_sample() / samples_per_pixel -
pixels_offset, (double)left);
@@ -495,7 +500,7 @@ void DecodeTrace::draw_annotation(const pv::data::decode::Annotation &a,
if (a.start_sample() == a.end_sample())
draw_instant(a, p, fill, outline, text_color, h,
- start, y);
+ start, y, min_annWidth);
else
draw_range(a, p, fill, outline, text_color, h,
start, end, y);
@@ -506,22 +511,31 @@ void DecodeTrace::draw_nodetail(QPainter &p,
size_t base_colour) const
{
const QRectF nodetail_rect(left, y - h/2 + 0.5, right - left, h);
- const size_t colour = base_colour % countof(Colours);
- const QColor &fill = Colours[colour];
+ QString info = tr("Zoom in For Detial");
+ int info_left = nodetail_rect.center().x() - p.boundingRect(QRectF(), 0, info).width();
+ int info_right = nodetail_rect.center().x() + p.boundingRect(QRectF(), 0, info).width();
+ int height = p.boundingRect(QRectF(), 0, info).height();
- p.setPen(Qt::white);
- p.setBrush(fill);
- p.drawRect(nodetail_rect);
- p.drawText(nodetail_rect, Qt::AlignCenter | Qt::AlignVCenter, "Zoom in for more detials");
+ p.setPen(Trace::DARK_FORE);
+ p.drawLine(left, y, info_left, y);
+ p.drawLine(info_right, y, right, y);
+ p.drawLine(info_left, y, info_left+5, y - height/2 + 0.5);
+ p.drawLine(info_left, y, info_left+5, y + height/2 + 0.5);
+ p.drawLine(info_right, y, info_right-5, y - height/2 + 0.5);
+ p.drawLine(info_right, y, info_right-5, y + height/2 + 0.5);
+
+ p.setPen(Trace::DARK_FORE);
+ p.drawText(nodetail_rect, Qt::AlignCenter | Qt::AlignVCenter, info);
}
void DecodeTrace::draw_instant(const pv::data::decode::Annotation &a, QPainter &p,
- QColor fill, QColor outline, QColor text_color, int h, double x, int y) const
+ QColor fill, QColor outline, QColor text_color, int h, double x, int y, double min_annWidth) const
{
const QString text = a.annotations().empty() ?
QString() : a.annotations().back();
- const double w = min((double)p.boundingRect(QRectF(), 0, text).width(),
- 0.0) + h;
+// const double w = min((double)p.boundingRect(QRectF(), 0, text).width(),
+// 0.0) + h;
+ const double w = min(min_annWidth, (double)h);
const QRectF rect(x - w / 2, y - h / 2, w, h);
p.setPen(outline);
@@ -564,7 +578,7 @@ void DecodeTrace::draw_range(const pv::data::decode::Annotation &a, QPainter &p,
QPointF(start + cap_width, bottom)
};
- p.setPen(Qt::white);
+ p.setPen(DARK_BACK);
p.drawConvexPolygon(pts, countof(pts));
if (annotations.empty())
@@ -643,20 +657,8 @@ bool DecodeTrace::draw_unresolved_period(QPainter &p, int h, int left,
return false;
const int y = get_y();
-// const double start = max(samples_decoded /
-// samples_per_pixel - pixels_offset, left - 1.0);
-// const double end = min(sample_count / samples_per_pixel -
-// pixels_offset, right + 1.0);
const QRectF no_decode_rect(left, y - h/2 + 0.5, right - left, h);
- p.setPen(QPen(Qt::NoPen));
- p.setBrush(Qt::white);
- p.drawRect(no_decode_rect);
-
- p.setPen(NoDecodeColour);
- p.setBrush(QBrush(NoDecodeColour, Qt::Dense7Pattern));
- p.drawRect(no_decode_rect);
-
const int progress100 = ceil(samples_decoded * 100.0 / need_sample_count);
p.setPen(dsLightBlue);
QFont font=p.font();
@@ -669,40 +671,40 @@ bool DecodeTrace::draw_unresolved_period(QPainter &p, int h, int left,
}
void DecodeTrace::draw_unshown_row(QPainter &p, int y, int h, int left,
- int right)
+ int right, QString info)
{
const QRectF unshown_rect(left, y - h/2 + 0.5, right - left, h);
+ int info_left = unshown_rect.center().x() - p.boundingRect(QRectF(), 0, info).width();
+ int info_right = unshown_rect.center().x() + p.boundingRect(QRectF(), 0, info).width();
+ int height = p.boundingRect(QRectF(), 0, info).height();
- p.setPen(QPen(Qt::NoPen));
- p.setBrush(QBrush(NoDecodeColour, Qt::Dense7Pattern));
- p.drawRect(unshown_rect);
+ p.setPen(Trace::DARK_FORE);
+ p.drawLine(left, y, info_left, y);
+ p.drawLine(info_right, y, right, y);
+ p.drawLine(info_left, y, info_left+5, y - height/2 + 0.5);
+ p.drawLine(info_left, y, info_left+5, y + height/2 + 0.5);
+ p.drawLine(info_right, y, info_right-5, y - height/2 + 0.5);
+ p.drawLine(info_right, y, info_right-5, y + height/2 + 0.5);
- p.setPen(dsLightBlue);
- QFont font=p.font();
- font.setPointSize(_view->get_signalHeight()*2/3);
- font.setBold(true);
- p.setFont(font);
- p.drawText(unshown_rect, Qt::AlignCenter | Qt::AlignVCenter, "Unshown");
+ p.setPen(Trace::DARK_FORE);
+ p.drawText(unshown_rect, Qt::AlignCenter | Qt::AlignVCenter, info);
}
-void DecodeTrace::create_decoder_form(int index,
+void DecodeTrace::create_decoder_form(
+ boost::shared_ptr &decoder_stack,
boost::shared_ptr &dec, QWidget *parent,
- QFormLayout *form)
+ QFormLayout *form)
{
const GSList *l;
- assert(dec);
+ assert(dec);
const srd_decoder *const decoder = dec->decoder();
assert(decoder);
- pv::widgets::DecoderGroupBox *const group =
- new pv::widgets::DecoderGroupBox(
- QString::fromUtf8(decoder->name));
- group->set_decoder_visible(dec->shown());
-
- _show_hide_mapper.setMapping(group, index);
- connect(group, SIGNAL(show_hide_decoder()),
- &_show_hide_mapper, SLOT(map()));
+ pv::widgets::DecoderGroupBox *const group =
+ new pv::widgets::DecoderGroupBox(decoder_stack, dec);
+ connect(group, SIGNAL(del_stack(boost::shared_ptr&)),
+ this, SLOT(on_del_stack(boost::shared_ptr&)));
QFormLayout *const decoder_form = new QFormLayout;
group->add_layout(decoder_form);
@@ -739,7 +741,7 @@ void DecodeTrace::create_decoder_form(int index,
// Add the options
boost::shared_ptr binding(
- new prop::binding::DecoderOptions(_decoder_stack, dec));
+ new prop::binding::DecoderOptions(decoder_stack, dec));
binding->add_properties_to_form(decoder_form, true);
_bindings.push_back(binding);
@@ -837,6 +839,7 @@ void DecodeTrace::on_decode_done()
_view->set_need_update(true);
_view->signals_changed();
}
+ _session.decode_done();
}
void DecodeTrace::on_delete()
@@ -860,33 +863,36 @@ void DecodeTrace::on_stack_decoder(srd_decoder *decoder)
create_popup_form();
}
-void DecodeTrace::on_show_hide_decoder(int index)
+void DecodeTrace::on_del_stack(boost::shared_ptr &dec)
{
- using pv::data::decode::Decoder;
+ assert(dec);
+ assert(_decoder_stack);
+ _decoder_stack->remove(dec);
- const list< boost::shared_ptr > stack(_decoder_stack->stack());
-
- // Find the decoder in the stack
- list< boost::shared_ptr >::const_iterator iter = stack.begin();
- for(int i = 0; i < index; i++, iter++)
- assert(iter != stack.end());
-
- boost::shared_ptr dec = *iter;
- assert(dec);
-
- const bool show = !dec->shown();
- dec->show(show);
-
- assert(index < (int)_decoder_forms.size());
- _decoder_forms[index]->set_decoder_visible(show);
-
- //_view->set_need_update(true);
+ create_popup_form();
}
-
int DecodeTrace::rows_size()
{
- return _decoder_stack->cur_rows_size();
+ using pv::data::decode::Decoder;
+
+ int size = 0;
+ BOOST_FOREACH(boost::shared_ptr dec,
+ _decoder_stack->stack()) {
+ if (dec->shown()) {
+ const std::map& rows(_decoder_stack->get_rows_gshow());
+ for (std::map::const_iterator i = rows.begin();
+ i != rows.end(); i++) {
+ if ((*i).first.decoder() == dec->decoder() &&
+ _decoder_stack->has_annotations((*i).first) &&
+ (*i).second)
+ size++;
+ }
+ } else {
+ size++;
+ }
+ }
+ return size == 0 ? 1 : size;
}
void DecodeTrace::paint_type_options(QPainter &p, int right, const QPoint pt)
@@ -897,9 +903,8 @@ void DecodeTrace::paint_type_options(QPainter &p, int right, const QPoint pt)
const QRectF group_index_rect = get_rect(CHNLREG, y, right);
QString index_string;
int last_index;
- p.setPen(Qt::transparent);
- p.setBrush(dsBlue);
- p.drawRect(group_index_rect);
+ p.setPen(QPen(DARK_FORE, 1, Qt::DashLine));
+ p.drawLine(group_index_rect.bottomLeft(), group_index_rect.bottomRight());
std::list::iterator i = _index_list.begin();
last_index = (*i);
index_string = QString::number(last_index);
@@ -912,7 +917,7 @@ void DecodeTrace::paint_type_options(QPainter &p, int right, const QPoint pt)
index_string = QString::number((*i)) + "," + index_string;
last_index = (*i);
}
- p.setPen(Qt::white);
+ p.setPen(DARK_FORE);
p.drawText(group_index_rect, Qt::AlignRight | Qt::AlignVCenter, index_string);
}
@@ -986,5 +991,6 @@ void DecodeTrace::frame_ended()
}
}
+
} // namespace view
} // namespace pv
diff --git a/DSView/pv/view/decodetrace.h b/DSView/pv/view/decodetrace.h
index 32f17bd9..553da4d9 100644
--- a/DSView/pv/view/decodetrace.h
+++ b/DSView/pv/view/decodetrace.h
@@ -152,14 +152,14 @@ private:
void draw_annotation(const pv::data::decode::Annotation &a, QPainter &p,
QColor text_colour, int text_height, int left, int right,
double samples_per_pixel, double pixels_offset, int y,
- size_t base_colour) const;
+ size_t base_colour, double min_annWidth) const;
void draw_nodetail(QPainter &p,
int text_height, int left, int right, int y,
size_t base_colour) const;
void draw_instant(const pv::data::decode::Annotation &a, QPainter &p,
QColor fill, QColor outline, QColor text_color, int h, double x,
- int y) const;
+ int y, double min_annWidth) const;
void draw_range(const pv::data::decode::Annotation &a, QPainter &p,
QColor fill, QColor outline, QColor text_color, int h, double start,
@@ -172,11 +172,11 @@ private:
int right);
void draw_unshown_row(QPainter &p, int y, int h, int left,
- int right);
+ int right, QString info);
- void create_decoder_form(int index,
- boost::shared_ptr &dec,
- QWidget *parent, QFormLayout *form);
+ void create_decoder_form(boost::shared_ptr &decoder_stack,
+ boost::shared_ptr &dec,
+ QWidget *parent, QFormLayout *form);
QComboBox* create_probe_selector(QWidget *parent,
const boost::shared_ptr &dec,
@@ -195,8 +195,7 @@ private slots:
void on_probe_selected(int);
void on_stack_decoder(srd_decoder *decoder);
-
- void on_show_hide_decoder(int index);
+ void on_del_stack(boost::shared_ptr &dec);
void on_decode_done();
@@ -219,7 +218,6 @@ private:
std::vector _cur_row_headings;
- QSignalMapper _show_hide_mapper;
QFormLayout *_popup_form;
QDialog *_popup;
};
diff --git a/DSView/pv/view/devmode.cpp b/DSView/pv/view/devmode.cpp
index f48c453c..2fb0a2b7 100644
--- a/DSView/pv/view/devmode.cpp
+++ b/DSView/pv/view/devmode.cpp
@@ -44,45 +44,50 @@ using namespace std;
namespace pv {
namespace view {
-DevMode::DevMode(View &parent) :
- QWidget(&parent),
- _view(parent),
- layout(new QGridLayout(this))
+DevMode::DevMode(QWidget *parent, SigSession &session) :
+ QWidget(parent),
+ _session(session),
+ _layout(new QGridLayout(this))
{
- setLayout(layout);
+ setLayout(_layout);
}
void DevMode::set_device()
{
int index = 0;
- const boost::shared_ptr dev_inst = _view.session().get_device();
+ const boost::shared_ptr dev_inst = _session.get_device();
assert(dev_inst);
+ for(std::map::const_iterator i = _mode_button_list.begin();
+ i != _mode_button_list.end(); i++) {
+ (*i).first->setParent(NULL);
+ _layout->removeWidget((*i).first);
+ delete (*i).first;
+ }
_mode_button_list.clear();
- delete layout;
- layout = new QGridLayout(this);
for (GSList *l = dev_inst->get_dev_mode_list();
l; l = l->next) {
sr_dev_mode *mode = (sr_dev_mode *)l->data;
- boost::shared_ptr mode_button = boost::shared_ptr(new QPushButton(NULL));
- mode_button->setFlat(true);
+ QPushButton *mode_button = new QPushButton(this);
+ //mode_button->setFlat(true);
mode_button->setText(mode->name);
+ mode_button->setCheckable(true);
_mode_button_list[mode_button] = mode;
+ if (dev_inst->dev_inst()->mode == _mode_button_list[mode_button]->mode)
+ mode_button->setChecked(true);
- connect(mode_button.get(), SIGNAL(clicked()), this, SLOT(on_mode_change()));
+ connect(mode_button, SIGNAL(clicked()), this, SLOT(on_mode_change()));
- layout->addWidget(mode_button.get(), index / GRID_COLS, index % GRID_COLS);
- layout->addWidget(new QWidget(), index / GRID_COLS, GRID_COLS);
- layout->setColumnStretch(GRID_COLS, 1);
+ _layout->addWidget(mode_button, index / GRID_COLS, index % GRID_COLS);
+ //layout->addWidget(new QWidget(), index / GRID_COLS, GRID_COLS);
+ _layout->setColumnStretch(GRID_COLS, 1);
index++;
- }
-
- setLayout(layout);
+ }
update();
}
@@ -94,40 +99,27 @@ void DevMode::paintEvent(QPaintEvent*)
o.initFrom(this);
QPainter painter(this);
style()->drawPrimitive(QStyle::PE_Widget, &o, &painter, this);
-
- painter.setRenderHint(QPainter::Antialiasing);
- painter.setPen(Qt::NoPen);
- for(std::map, sr_dev_mode *>::const_iterator i = _mode_button_list.begin();
- i != _mode_button_list.end(); i++) {
- const boost::shared_ptr dev_inst = _view.session().get_device();
- assert(dev_inst);
- if (dev_inst->dev_inst()->mode == (*i).second->mode)
- painter.setBrush(Trace::dsBlue);
- else
- painter.setBrush(Trace::dsGray);
-
- painter.drawRoundedRect((*i).first->geometry(), 4, 4);
- }
-
- painter.end();
}
void DevMode::on_mode_change()
{
- const boost::shared_ptr dev_inst = _view.session().get_device();
+ const boost::shared_ptr dev_inst = _session.get_device();
assert(dev_inst);
QPushButton *button = qobject_cast(sender());
- for(std::map, sr_dev_mode *>::const_iterator i = _mode_button_list.begin();
+ for(std::map::const_iterator i = _mode_button_list.begin();
i != _mode_button_list.end(); i++) {
- if ((*i).first.get() == button) {
+ if ((*i).first == button) {
if (dev_inst->dev_inst()->mode != (*i).second->mode) {
- _view.session().stop_capture();
+ _session.stop_capture();
dev_inst->set_config(NULL, NULL,
SR_CONF_DEVICE_MODE,
g_variant_new_int16((*i).second->mode));
+ button->setChecked(true);
mode_changed();
}
+ } else {
+ (*i).first->setChecked(false);
}
}
}
diff --git a/DSView/pv/view/devmode.h b/DSView/pv/view/devmode.h
index 27488805..3e114fbb 100644
--- a/DSView/pv/view/devmode.h
+++ b/DSView/pv/view/devmode.h
@@ -44,9 +44,9 @@ namespace device{
class DevInst;
}
-namespace view {
+class SigSession;
-class View;
+namespace view {
class DevMode : public QWidget
{
@@ -56,7 +56,7 @@ private:
static const int GRID_COLS = 3;
public:
- DevMode(View &parent);
+ DevMode(QWidget *parent, SigSession &session);
private:
void paintEvent(QPaintEvent *event);
@@ -77,10 +77,10 @@ signals:
void mode_changed();
private:
- View &_view;
+ SigSession &_session;
- QGridLayout * layout;
- std::map , sr_dev_mode *> _mode_button_list;
+ QGridLayout * _layout;
+ std::map _mode_button_list;
QPoint _mouse_point;
};
diff --git a/DSView/pv/view/groupsignal.cpp b/DSView/pv/view/groupsignal.cpp
index 0c674dfd..aec24c5b 100644
--- a/DSView/pv/view/groupsignal.cpp
+++ b/DSView/pv/view/groupsignal.cpp
@@ -204,9 +204,8 @@ void GroupSignal::paint_type_options(QPainter &p, int right, const QPoint pt)
const QRectF group_index_rect = get_rect(CHNLREG, y, right);
QString index_string;
int last_index;
- p.setPen(Qt::transparent);
- p.setBrush(dsBlue);
- p.drawRect(group_index_rect);
+ p.setPen(QPen(DARK_FORE, 1, Qt::DashLine));
+ p.drawLine(group_index_rect.bottomLeft(), group_index_rect.bottomRight());
std::list::iterator i = _index_list.begin();
last_index = (*i);
index_string = QString::number(last_index);
@@ -219,7 +218,7 @@ void GroupSignal::paint_type_options(QPainter &p, int right, const QPoint pt)
index_string = QString::number((*i)) + "," + index_string;
last_index = (*i);
}
- p.setPen(Qt::white);
+ p.setPen(DARK_FORE);
p.drawText(group_index_rect, Qt::AlignRight | Qt::AlignVCenter, index_string);
}
diff --git a/DSView/pv/view/header.cpp b/DSView/pv/view/header.cpp
index e6d20c37..ca38299f 100644
--- a/DSView/pv/view/header.cpp
+++ b/DSView/pv/view/header.cpp
@@ -115,15 +115,13 @@ void Header::paintEvent(QPaintEvent*)
QStyleOption o;
o.initFrom(this);
QPainter painter(this);
+ //painter.setRenderHint(QPainter::Antialiasing);
style()->drawPrimitive(QStyle::PE_Widget, &o, &painter, this);
const int w = width();
const vector< boost::shared_ptr > traces(
_view.get_traces());
- //QPainter painter(this);
- //painter.setRenderHint(QPainter::Antialiasing);
-
const bool dragging = !_drag_traces.empty();
BOOST_FOREACH(const boost::shared_ptr t, traces)
{
diff --git a/DSView/pv/view/logicsignal.cpp b/DSView/pv/view/logicsignal.cpp
index 4bbe9ad0..00df932b 100644
--- a/DSView/pv/view/logicsignal.cpp
+++ b/DSView/pv/view/logicsignal.cpp
@@ -44,24 +44,7 @@ const QColor LogicSignal::EdgeColour(0x80, 0x80, 0x80);
const QColor LogicSignal::HighColour(0x00, 0xC0, 0x00);
const QColor LogicSignal::LowColour(0xC0, 0x00, 0x00);
-const QColor LogicSignal::SignalColours[8] = {
- QColor(0x16, 0x19, 0x1A), // Black
- QColor(0x8F, 0x52, 0x02), // Brown
- QColor(0xCC, 0x00, 0x00), // Red
- QColor(0xF5, 0x79, 0x00), // Orange
- QColor(0xED, 0xD4, 0x00), // Yellow
- QColor(0x73, 0xD2, 0x16), // Green
- QColor(0x34, 0x65, 0xA4), // Blue
- QColor(0x75, 0x50, 0x7B), // Violet
-// QColor(17, 133, 209),
-// QColor(17, 133, 209),
-// QColor(17, 133, 209),
-// QColor(17, 133, 209),
-// QColor(17, 133, 209),
-// QColor(17, 133, 209),
-// QColor(17, 133, 209),
-// QColor(17, 133, 209),
-};
+const QColor LogicSignal::DEFAULT_COLOR = QColor(150, 150, 150, 255);
const int LogicSignal::StateHeight = 12;
const int LogicSignal::StateRound = 5;
@@ -73,7 +56,8 @@ LogicSignal::LogicSignal(boost::shared_ptr dev_inst,
_data(data),
_trig(NONTRIG)
{
- _colour = SignalColours[probe->index % countof(SignalColours)];
+ //_colour = PROBE_COLORS[probe->index % countof(PROBE_COLORS)];
+ _colour = DEFAULT_COLOR;
}
LogicSignal::LogicSignal(boost::shared_ptr s,
@@ -249,35 +233,37 @@ void LogicSignal::paint_type_options(QPainter &p, int right, const QPoint pt)
const QRectF lowTrig_rect = get_rect(LOWTRIG, y, right);
const QRectF edgeTrig_rect = get_rect(EDGTRIG, y, right);
- p.setPen(Qt::transparent);
- p.setBrush(posTrig_rect.contains(pt) ? dsYellow.darker() :
- (_trig == POSTRIG) ? dsYellow : dsBlue);
+ p.setPen(Qt::NoPen);
+ p.setBrush(posTrig_rect.contains(pt) ? dsBlue.lighter() :
+ (_trig == POSTRIG) ? dsBlue : DARK_BACK);
p.drawRect(posTrig_rect);
- p.setBrush(higTrig_rect.contains(pt) ? dsYellow.darker() :
- (_trig == HIGTRIG) ? dsYellow : dsBlue);
+ p.setBrush(higTrig_rect.contains(pt) ? dsBlue.lighter() :
+ (_trig == HIGTRIG) ? dsBlue : DARK_BACK);
p.drawRect(higTrig_rect);
- p.setBrush(negTrig_rect.contains(pt) ? dsYellow.darker() :
- (_trig == NEGTRIG) ? dsYellow : dsBlue);
+ p.setBrush(negTrig_rect.contains(pt) ? dsBlue.lighter() :
+ (_trig == NEGTRIG) ? dsBlue : DARK_BACK);
p.drawRect(negTrig_rect);
- p.setBrush(lowTrig_rect.contains(pt) ? dsYellow.darker() :
- (_trig == LOWTRIG) ? dsYellow : dsBlue);
+ p.setBrush(lowTrig_rect.contains(pt) ? dsBlue.lighter() :
+ (_trig == LOWTRIG) ? dsBlue : DARK_BACK);
p.drawRect(lowTrig_rect);
- p.setBrush(edgeTrig_rect.contains(pt) ? dsYellow.darker() :
- (_trig == EDGTRIG) ? dsYellow : dsBlue);
+ p.setBrush(edgeTrig_rect.contains(pt) ? dsBlue.lighter() :
+ (_trig == EDGTRIG) ? dsBlue : DARK_BACK);
p.drawRect(edgeTrig_rect);
- p.setPen(QPen(Qt::blue, 1, Qt::DotLine));
+ p.setPen(QPen(DARK_FORE, 1, Qt::DashLine));
p.setBrush(Qt::transparent);
- p.drawLine(posTrig_rect.right(), posTrig_rect.top() + 3,
- posTrig_rect.right(), posTrig_rect.bottom() - 3);
- p.drawLine(higTrig_rect.right(), higTrig_rect.top() + 3,
- higTrig_rect.right(), higTrig_rect.bottom() - 3);
- p.drawLine(negTrig_rect.right(), negTrig_rect.top() + 3,
- negTrig_rect.right(), negTrig_rect.bottom() - 3);
- p.drawLine(lowTrig_rect.right(), lowTrig_rect.top() + 3,
- lowTrig_rect.right(), lowTrig_rect.bottom() - 3);
+// p.drawLine(posTrig_rect.right(), posTrig_rect.top(),
+// posTrig_rect.right(), posTrig_rect.bottom());
+// p.drawLine(higTrig_rect.right(), higTrig_rect.top(),
+// higTrig_rect.right(), higTrig_rect.bottom());
+// p.drawLine(negTrig_rect.right(), negTrig_rect.top(),
+// negTrig_rect.right(), negTrig_rect.bottom());
+// p.drawLine(lowTrig_rect.right(), lowTrig_rect.top(),
+// lowTrig_rect.right(), lowTrig_rect.bottom());
+ p.drawLine(posTrig_rect.left(), posTrig_rect.bottom(),
+ edgeTrig_rect.right(), edgeTrig_rect.bottom());
- p.setPen(QPen(Qt::white, 2, Qt::SolidLine));
+ p.setPen(QPen(DARK_FORE, 2, Qt::SolidLine));
p.setBrush(Qt::transparent);
p.drawLine(posTrig_rect.left() + 5, posTrig_rect.bottom() - 5,
posTrig_rect.center().x(), posTrig_rect.bottom() - 5);
diff --git a/DSView/pv/view/logicsignal.h b/DSView/pv/view/logicsignal.h
index 5f4ba7d1..3daa567b 100644
--- a/DSView/pv/view/logicsignal.h
+++ b/DSView/pv/view/logicsignal.h
@@ -48,7 +48,7 @@ private:
static const QColor HighColour;
static const QColor LowColour;
- static const QColor SignalColours[8];
+ static const QColor DEFAULT_COLOR;
static const int StateHeight;
static const int StateRound;
diff --git a/DSView/pv/view/ruler.cpp b/DSView/pv/view/ruler.cpp
index 0a3b8015..3fdab4b9 100644
--- a/DSView/pv/view/ruler.cpp
+++ b/DSView/pv/view/ruler.cpp
@@ -77,6 +77,7 @@ const QColor Ruler::dsBlue = QColor(17, 133, 209, 255);
const QColor Ruler::dsYellow = QColor(238, 178, 17, 255);
const QColor Ruler::dsRed = QColor(213, 15, 37, 255);
const QColor Ruler::dsGreen = QColor(0, 153, 37, 255);
+const QColor Ruler::RULER_COLOR = QColor(255, 255, 255, 255);
const QColor Ruler::HitColor = dsYellow;
const QColor Ruler::WarnColor = dsRed;
@@ -458,7 +459,7 @@ void Ruler::draw_logic_tick_mark(QPainter &p)
AlignLeft | AlignTop, "8").height();
// Draw the tick marks
- p.setPen(dsBlue);
+ p.setPen(Trace::DARK_FORE);
const double minor_tick_period = tick_period / MinPeriodScale;
const int minor_order = (int)floorf(log10f(minor_tick_period));
@@ -548,7 +549,7 @@ void Ruler::draw_hover_mark(QPainter &p)
return;
p.setPen(QPen(Qt::NoPen));
- p.setBrush(dsBlue);
+ p.setBrush(RULER_COLOR);
const int b = height() - 1;
const QPointF points[] = {
diff --git a/DSView/pv/view/ruler.h b/DSView/pv/view/ruler.h
index c22d8cce..d3389bdc 100644
--- a/DSView/pv/view/ruler.h
+++ b/DSView/pv/view/ruler.h
@@ -54,6 +54,7 @@ private:
static const QColor dsYellow;
static const QColor dsRed;
static const QColor dsGreen;
+ static const QColor RULER_COLOR;
public:
static const QColor CursorColor[8];
diff --git a/DSView/pv/view/trace.cpp b/DSView/pv/view/trace.cpp
index 52d522d5..3c79bc1a 100644
--- a/DSView/pv/view/trace.cpp
+++ b/DSView/pv/view/trace.cpp
@@ -50,6 +50,29 @@ const QColor Trace::dsLightBlue = QColor(17, 133, 209, 150);
const QColor Trace::dsLightRed = QColor(213, 15, 37, 150);
const QPen Trace::SignalAxisPen = QColor(128, 128, 128, 64);
+const QColor Trace::DARK_BACK = QColor(48, 47, 47, 255);
+const QColor Trace::DARK_FORE = QColor(150, 150, 150, 255);
+const QColor Trace::DARK_HIGHLIGHT = QColor(32, 32, 32, 255);
+
+const QColor Trace::PROBE_COLORS[8] = {
+ QColor(0x50, 0x50, 0x50), // Black
+ QColor(0x8F, 0x52, 0x02), // Brown
+ QColor(0xCC, 0x00, 0x00), // Red
+ QColor(0xF5, 0x79, 0x00), // Orange
+ QColor(0xED, 0xD4, 0x00), // Yellow
+ QColor(0x73, 0xD2, 0x16), // Green
+ QColor(0x34, 0x65, 0xA4), // Blue
+ QColor(0x75, 0x50, 0x7B), // Violet
+// QColor(17, 133, 209),
+// QColor(17, 133, 209),
+// QColor(17, 133, 209),
+// QColor(17, 133, 209),
+// QColor(17, 133, 209),
+// QColor(17, 133, 209),
+// QColor(17, 133, 209),
+// QColor(17, 133, 209),
+};
+
const QPen Trace::AxisPen(QColor(128, 128, 128, 64));
const int Trace::LabelHitPadding = 2;
@@ -220,14 +243,14 @@ void Trace::paint_label(QPainter &p, int right, const QPoint pt)
const QRectF name_rect = get_rect("name", y, right);
const QRectF label_rect = get_rect("label", get_zeroPos(), right);
- p.setRenderHint(QPainter::Antialiasing);
+ //p.setRenderHint(QPainter::Antialiasing);
// Paint the ColorButton
p.setPen(Qt::transparent);
p.setBrush(enabled() ? _colour : dsDisable);
p.drawRect(color_rect);
// Paint the signal name
- p.setPen(enabled() ? Qt::black : dsDisable);
+ p.setPen(enabled() ? DARK_FORE: dsDisable);
p.drawText(name_rect, Qt::AlignLeft | Qt::AlignVCenter, _name);
// Paint the trigButton
@@ -244,16 +267,14 @@ void Trace::paint_label(QPainter &p, int right, const QPoint pt)
};
p.setPen(Qt::transparent);
- if (_type == SR_CHANNEL_DSO)
+ if (_type == SR_CHANNEL_DSO) {
p.setBrush((label_rect.contains(pt) || selected()) ? _colour.darker() : _colour);
- else
- p.setBrush((label_rect.contains(pt) || selected()) ? dsYellow : dsBlue);
- p.drawPolygon(points, countof(points));
-
- p.setPen(QPen(Qt::blue, 1, Qt::DotLine));
- p.setBrush(Qt::transparent);
- p.drawLine(label_rect.right(), label_rect.top() + 3,
- label_rect.right(), label_rect.bottom() - 3);
+ p.drawPolygon(points, countof(points));
+ } else {
+ QColor color = PROBE_COLORS[*_index_list.begin() % countof(PROBE_COLORS)];
+ p.setBrush((label_rect.contains(pt) || selected()) ? color.lighter() : color);
+ p.drawPolygon(points, countof(points));
+ }
// Paint the text
p.setPen(Qt::white);
@@ -326,30 +347,6 @@ void Trace::compute_text_size(QPainter &p)
p.boundingRect(QRectF(), 0, "99").height());
}
-QRectF Trace::get_rect(const char *s, int y, int right)
-{
- const QSizeF color_size(SquareWidth, SquareWidth);
- const QSizeF name_size(right - get_leftWidth() - get_rightWidth(), SquareWidth);
- //const QSizeF label_size(_text_size.width() + Margin, SquareWidth);
- const QSizeF label_size(SquareWidth, SquareWidth);
-
- if (!strcmp(s, "name"))
- return QRectF(
- get_leftWidth(),
- y - name_size.height() / 2,
- name_size.width(), name_size.height());
- else if (!strcmp(s, "label"))
- return QRectF(
- right - 1.5f * label_size.width(),
- y - SquareWidth / 2,
- label_size.width(), label_size.height());
- else
- return QRectF(
- 2,
- y - SquareWidth / 2,
- SquareWidth, SquareWidth);
-}
-
QRectF Trace::get_view_rect() const
{
assert(_view);
@@ -385,7 +382,7 @@ int Trace::rows_size()
int Trace::get_leftWidth() const
{
- return SquareWidth + Margin;
+ return SquareWidth/2 + Margin;
}
int Trace::get_rightWidth() const
@@ -398,5 +395,34 @@ int Trace::get_headerHeight() const
return SquareWidth;
}
+QRectF Trace::get_rect(const char *s, int y, int right) const
+{
+ const QSizeF color_size(get_leftWidth() - Margin, SquareWidth);
+ const QSizeF name_size(right - get_leftWidth() - get_rightWidth(), SquareWidth);
+ //const QSizeF label_size(_text_size.width() + Margin, SquareWidth);
+ const QSizeF label_size(SquareWidth, SquareWidth);
+
+ if (!strcmp(s, "name"))
+ return QRectF(
+ get_leftWidth(),
+ y - name_size.height() / 2,
+ name_size.width(), name_size.height());
+ else if (!strcmp(s, "label"))
+ return QRectF(
+ right - 1.5f * label_size.width(),
+ y - label_size.height() / 2,
+ label_size.width(), label_size.height());
+ else if (!strcmp(s, "color"))
+ return QRectF(
+ 2,
+ y - color_size.height() / 2,
+ color_size.width(), color_size.height());
+ else
+ return QRectF(
+ 2,
+ y - SquareWidth / 2,
+ SquareWidth, SquareWidth);
+}
+
} // namespace view
} // namespace pv
diff --git a/DSView/pv/view/trace.h b/DSView/pv/view/trace.h
index 329400bd..26d9b504 100644
--- a/DSView/pv/view/trace.h
+++ b/DSView/pv/view/trace.h
@@ -70,6 +70,12 @@ public:
static const QColor dsLightRed;
static const QPen SignalAxisPen;
+ static const QColor DARK_BACK;
+ static const QColor DARK_FORE;
+ static const QColor DARK_HIGHLIGHT;
+
+ static const QColor PROBE_COLORS[8];
+
protected:
Trace(QString name, uint16_t index, int type);
Trace(QString name, std::list index_list, int type, int sec_index);
@@ -225,7 +231,7 @@ public:
* area.
* @return Returns the rectangle of the signal label.
*/
- QRectF get_rect(const char *s, int y, int right);
+ QRectF get_rect(const char *s, int y, int right) const;
virtual int rows_size();
diff --git a/DSView/pv/view/view.cpp b/DSView/pv/view/view.cpp
index e421a8ce..df0e2e87 100644
--- a/DSView/pv/view/view.cpp
+++ b/DSView/pv/view/view.cpp
@@ -74,7 +74,7 @@ View::View(SigSession &session, pv::toolbars::SamplingBar *sampling_bar, QWidget
_viewport(new Viewport(*this)),
_ruler(new Ruler(*this)),
_header(new Header(*this)),
- _devmode(new DevMode(*this)),
+ _devmode(new DevMode(this, session)),
_scale(1e-8),
_preScale(1e-6),
_maxscale(1e9),
@@ -98,15 +98,17 @@ View::View(SigSession &session, pv::toolbars::SamplingBar *sampling_bar, QWidget
setViewportMargins(headerWidth(), RulerHeight, 0, 0);
setViewport(_viewport);
+ connect(&_session, SIGNAL(device_setted()),
+ _devmode, SLOT(set_device()));
connect(&_session, SIGNAL(signals_changed()),
this, SLOT(signals_changed()));
connect(&_session, SIGNAL(data_updated()),
this, SLOT(data_updated()));
connect(&_session, SIGNAL(receive_trigger(quint64)),
this, SLOT(set_trig_pos(quint64)));
+ connect(&_session, SIGNAL(show_region(uint64_t,uint64_t)),
+ this, SLOT(show_region(uint64_t, uint64_t)));
- connect(&_session, SIGNAL(device_setted()),
- _devmode, SLOT(set_device()));
connect(_devmode, SIGNAL(mode_changed()),
this, SIGNAL(mode_changed()));
@@ -464,9 +466,9 @@ void View::update_scale()
}
_minscale = (1.0 / sample_rate) / MaxPixelsPerSample;
- _offset = 0;
+ //_offset = 0;
_preScale = _scale;
- _preOffset = _offset;
+ //_preOffset = _offset;
_trig_cursor->set_index(_trig_pos);
@@ -514,6 +516,7 @@ void View::signals_changed()
_viewport->clear_measure();
header_updated();
normalize_layout();
+ data_updated();
}
bool View::eventFilter(QObject *object, QEvent *event)
@@ -834,5 +837,14 @@ QString View::trigger_time()
return _trigger_time.toString("yyyy-MM-dd hh:mm:ss ddd");
}
+void View::show_region(uint64_t start, uint64_t end)
+{
+ assert(start <= end);
+ const double ideal_scale = (end-start) * 2.0 / _session.get_device()->get_sample_rate() / get_view_width();
+ const double new_scale = max(min(ideal_scale, _maxscale), _minscale);
+ const double new_off = (start + end) * 0.5 / _session.get_device()->get_sample_rate() - new_scale * get_view_width() / 2;
+ set_scale_offset(new_scale, new_off);
+}
+
} // namespace view
} // namespace pv
diff --git a/DSView/pv/view/view.h b/DSView/pv/view/view.h
index 27fabea0..1f903737 100644
--- a/DSView/pv/view/view.h
+++ b/DSView/pv/view/view.h
@@ -221,6 +221,7 @@ public slots:
void signals_changed();
void data_updated();
void update_scale();
+ void show_region(uint64_t start, uint64_t end);
private slots:
diff --git a/DSView/pv/view/viewport.cpp b/DSView/pv/view/viewport.cpp
index c53e5d51..4f5b6f67 100644
--- a/DSView/pv/view/viewport.cpp
+++ b/DSView/pv/view/viewport.cpp
@@ -445,11 +445,11 @@ void Viewport::mouseMoveEvent(QMouseEvent *event)
if (_action_type == DSO_YM)
_dso_ym_end = event->pos().y();
-
- measure();
}
_mouse_point = event->pos();
+
+ measure();
update();
}
@@ -719,7 +719,6 @@ void Viewport::leaveEvent(QEvent *)
_mm_period = "#####";
_mm_freq = "#####";
_mm_duty = "#####";
- measure_updated();
} else if (_action_type == DSO_YM) {
_dso_ym_valid = false;
}
@@ -727,6 +726,7 @@ void Viewport::leaveEvent(QEvent *)
if (_action_type != NO_ACTION)
_action_type = NO_ACTION;
+ measure();
update();
}
@@ -767,7 +767,7 @@ void Viewport::measure()
boost::shared_ptr dsoSig;
if (logicSig = dynamic_pointer_cast(s)) {
if (_action_type == NO_ACTION) {
- if (logicSig->measure(_view.hover_point(), _cur_sample, _nxt_sample, _thd_sample)) {
+ if (logicSig->measure(_mouse_point, _cur_sample, _nxt_sample, _thd_sample)) {
_measure_type = LOGIC_FREQ;
_mm_width = _view.get_ruler()->format_real_time(_nxt_sample - _cur_sample, sample_rate);
@@ -1173,7 +1173,7 @@ void Viewport::on_drag_timer()
void Viewport::paintTrigTime(QPainter &p)
{
if (_view.session().get_device()->dev_inst()->mode == LOGIC) {
- p.setPen(Trace::dsBack);
+ p.setPen(Trace::DARK_FORE);
p.drawText(this->rect(), Qt::AlignRight | Qt::AlignBottom,
"Last Trigger Time: "+_view.trigger_time());
}
diff --git a/DSView/pv/widgets/decodergroupbox.cpp b/DSView/pv/widgets/decodergroupbox.cpp
index 3b4ec20a..d03082e6 100644
--- a/DSView/pv/widgets/decodergroupbox.cpp
+++ b/DSView/pv/widgets/decodergroupbox.cpp
@@ -17,52 +17,134 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
+extern "C" {
+#include
+}
#include "decodergroupbox.h"
+#include "../data/decoderstack.h"
+#include "../data/decode/decoder.h"
+#include "../data/decode/row.h"
#include
#include
#include
#include
+#include
+
+#include
#include
namespace pv {
namespace widgets {
-DecoderGroupBox::DecoderGroupBox(QString title, QWidget *parent) :
- QWidget(parent),
- _layout(new QGridLayout),
- _show_hide_button(QIcon(":/icons/shown.png"), QString(), this)
+DecoderGroupBox::DecoderGroupBox(boost::shared_ptr &decoder_stack,
+ boost::shared_ptr &dec,
+ QWidget *parent) :
+ QWidget(parent),
+ _decoder_stack(decoder_stack),
+ _dec(dec),
+ _layout(new QGridLayout)
{
_layout->setContentsMargins(0, 0, 0, 0);
- setLayout(_layout);
+ setLayout(_layout);
- _layout->addWidget(new QLabel(QString("%1
").arg(title)),
+ _layout->addWidget(new QLabel(QString("%1
").arg(_dec->decoder()->name)),
0, 0);
_layout->setColumnStretch(0, 1);
- QHBoxLayout *const toolbar = new QHBoxLayout;
- _layout->addLayout(toolbar, 0, 1);
+ const srd_decoder *const d = _dec->decoder();
+ assert(d);
+ const bool have_probes = (d->channels || d->opt_channels) != 0;
+ if (!have_probes) {
+ _del_button = new QPushButton(QIcon(":/icons/del.png"), QString(), this);
+ _layout->addWidget(_del_button, 0, 1);
+ connect(_del_button, SIGNAL(clicked()), this, SLOT(on_del_stack()));
+ }
- _show_hide_button.setFlat(true);
- //_show_hide_button.setIconSize(QSize(16, 16));
- connect(&_show_hide_button, SIGNAL(clicked()),
- this, SIGNAL(show_hide_decoder()));
- toolbar->addWidget(&_show_hide_button);
+ _index = 0;
+ BOOST_FOREACH(boost::shared_ptr dec,
+ _decoder_stack->stack()) {
+ if (dec == _dec)
+ break;
+ _index++;
+ }
+ _show_button = new QPushButton(QIcon(_dec->shown() ?
+ ":/icons/shown.png" :
+ ":/icons/hidden.png"), QString(), this);
+ _show_button->setProperty("index", -1);
+ connect(_show_button, SIGNAL(clicked()),
+ this, SLOT(tog_icon()));
+ _layout->addWidget(_show_button, 0, 2);
+
+
+ // add row show/hide
+ int index = 0;
+ const std::map& rows(_decoder_stack->get_rows_gshow());
+ for (std::map::const_iterator i = rows.begin();
+ i != rows.end(); i++) {
+ if ((*i).first.decoder() == _dec->decoder()) {
+ QPushButton *show_button = new QPushButton(QIcon((*i).second ?
+ ":/icons/shown.png" :
+ ":/icons/hidden.png"), QString(), this);
+ show_button->setProperty("index", index);
+ connect(show_button, SIGNAL(clicked()), this, SLOT(tog_icon()));
+ _row_show_button.push_back(show_button);
+ _layout->addWidget(new QLabel((*i).first.title(), this), _row_show_button.size(), 0);
+ _layout->addWidget(show_button, _row_show_button.size(), 2);
+ }
+ index++;
+ }
}
void DecoderGroupBox::add_layout(QLayout *layout)
{
assert(layout);
- _layout->addLayout(layout, 1, 0, 1, 2);
+ _layout->addLayout(layout, _row_show_button.size()+1, 0, 1, 3);
}
-void DecoderGroupBox::set_decoder_visible(bool visible)
+void DecoderGroupBox::tog_icon()
{
- _show_hide_button.setIcon(QIcon(visible ?
- ":/icons/shown.png" :
- ":/icons/hidden.png"));
+ QPushButton *sc = dynamic_cast(sender());
+ QVariant id = sc->property("index");
+ int index = id.toInt();
+ if (index == -1) {
+ int i = _index;
+ BOOST_FOREACH(boost::shared_ptr dec,
+ _decoder_stack->stack()) {
+ if (i-- == 0) {
+ dec->show(!dec->shown());
+ sc->setIcon(QIcon(dec->shown() ? ":/icons/shown.png" :
+ ":/icons/hidden.png"));
+ break;
+ }
+ }
+ } else {
+ std::map& rows(_decoder_stack->get_rows_gshow());
+ for (std::map::const_iterator i = rows.begin();
+ i != rows.end(); i++) {
+ if (index-- == 0) {
+ _decoder_stack->set_rows_gshow((*i).first, !(*i).second);
+ //rows[(*i).first] = !(*i).second;
+ sc->setIcon(QIcon(rows[(*i).first] ? ":/icons/shown.png" :
+ ":/icons/hidden.png"));
+ break;
+ }
+ }
+ }
+}
+
+void DecoderGroupBox::on_del_stack()
+{
+ int i = _index;
+ BOOST_FOREACH(boost::shared_ptr dec,
+ _decoder_stack->stack()) {
+ if (i-- == 0) {
+ del_stack(dec);
+ break;
+ }
+ }
}
} // widgets
diff --git a/DSView/pv/widgets/decodergroupbox.h b/DSView/pv/widgets/decodergroupbox.h
index 07878ae2..c69543d5 100644
--- a/DSView/pv/widgets/decodergroupbox.h
+++ b/DSView/pv/widgets/decodergroupbox.h
@@ -22,11 +22,19 @@
#define DSVIEW_PV_WIDGETS_DECODERGROUPBOX_H
#include
-
-class QGridLayout;
-class QToolBar;
+#include
+#include
+#include