From: Jens S. <jen...@gm...> - 2014-05-22 20:05:44
|
These patches add small changes for stuff that I found missing when using PulseView, and others may find useful too. Jens Steinhauser (13): MainWindow: Add shortcuts for the open/save menu items. MainWindow: Remember directory of last file that was opened/saved. MainWindow: Add missing toolbar buttons. MainWindow: Zoom fit after opening a capature file. SigSession: Fix typo in comment. SamplingBar: Show total sampling time in a tooltip. Put the time format function into a separate file. SamplingBar: Use nicer time format in the tooltip. Use a separate widget to hold the cursor labels. View: Hide the cursorheader with the cursors. CursorHeader: Make the size dependend on the used font. CursorHeader: Use the same number format as the ruler. Header: Invisible traces shouldn't influence the width. CMakeLists.txt | 3 + main.cpp | 2 +- pv/mainwindow.cpp | 45 ++++++++++- pv/sigsession.cpp | 4 +- pv/toolbars/samplingbar.cpp | 22 ++++++ pv/toolbars/samplingbar.h | 3 + pv/util.cpp | 72 +++++++++++++++++ pv/util.h | 59 ++++++++++++++ pv/view/cursor.cpp | 6 +- pv/view/cursorheader.cpp | 143 ++++++++++++++++++++++++++++++++++ pv/view/cursorheader.h | 65 ++++++++++++++++ pv/view/cursorpair.cpp | 6 +- pv/view/header.cpp | 11 ++- pv/view/header.h | 2 +- pv/view/marginwidget.cpp | 4 + pv/view/marginwidget.h | 2 +- pv/view/ruler.cpp | 186 +++++++++++--------------------------------- pv/view/ruler.h | 30 +++---- pv/view/view.cpp | 43 +++++++--- pv/view/view.h | 2 + 20 files changed, 518 insertions(+), 192 deletions(-) create mode 100644 pv/util.cpp create mode 100644 pv/util.h create mode 100644 pv/view/cursorheader.cpp create mode 100644 pv/view/cursorheader.h -- 1.9.0 |
From: Jens S. <jen...@gm...> - 2014-05-22 20:05:30
|
--- pv/mainwindow.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pv/mainwindow.cpp b/pv/mainwindow.cpp index 0089b11..77e77a1 100644 --- a/pv/mainwindow.cpp +++ b/pv/mainwindow.cpp @@ -123,6 +123,7 @@ void MainWindow::setup_ui() "MainWindow", "&Open...", 0, QApplication::UnicodeUTF8)); action_open->setIcon(QIcon::fromTheme("document-open", QIcon(":/icons/document-open.png"))); + action_open->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_O)); action_open->setObjectName(QString::fromUtf8("actionOpen")); menu_file->addAction(action_open); @@ -131,6 +132,7 @@ void MainWindow::setup_ui() "MainWindow", "&Save As...", 0, QApplication::UnicodeUTF8)); action_save_as->setIcon(QIcon::fromTheme("document-save-as", QIcon(":/icons/document-save-as.png"))); + action_save_as->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_S)); action_save_as->setObjectName(QString::fromUtf8("actionSaveAs")); menu_file->addAction(action_save_as); -- 1.9.0 |
From: Jens S. <jen...@gm...> - 2014-05-22 20:05:33
|
--- main.cpp | 2 +- pv/mainwindow.cpp | 25 ++++++++++++++++++++++--- 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/main.cpp b/main.cpp index 2c6a59e..5ff61d9 100644 --- a/main.cpp +++ b/main.cpp @@ -69,7 +69,7 @@ int main(int argc, char *argv[]) // Set some application metadata QApplication::setApplicationVersion(PV_VERSION_STRING); QApplication::setApplicationName("PulseView"); - QApplication::setOrganizationDomain("http://www.sigrok.org"); + QApplication::setOrganizationDomain("sigrok.org"); // Parse arguments while (1) { diff --git a/pv/mainwindow.cpp b/pv/mainwindow.cpp index 77e77a1..efb2f32 100644 --- a/pv/mainwindow.cpp +++ b/pv/mainwindow.cpp @@ -35,6 +35,7 @@ #include <QMessageBox> #include <QMenu> #include <QMenuBar> +#include <QSettings> #include <QStatusBar> #include <QVBoxLayout> #include <QWidget> @@ -340,13 +341,23 @@ void MainWindow::show_session_error( void MainWindow::on_actionOpen_triggered() { + // Get the directory containing the last file that was opened + const char* setting_name = "MainWindow/OpenDirectory"; + QSettings settings; + QString dir = settings.value(setting_name).toString(); + // Show the dialog const QString file_name = QFileDialog::getOpenFileName( - this, tr("Open File"), "", tr( + this, tr("Open File"), dir, tr( "Sigrok Sessions (*.sr);;" "All Files (*.*)")); - if (!file_name.isEmpty()) + + if (!file_name.isEmpty()) { load_file(file_name); + + QString abs_path = QFileInfo(file_name).absolutePath(); + settings.setValue(setting_name, abs_path); + } } void MainWindow::on_actionSaveAs_triggered() @@ -356,13 +367,21 @@ void MainWindow::on_actionSaveAs_triggered() // Stop any currently running capture session _session.stop_capture(); + // Get the directory containing the last file that was saved + const char* setting_name = "MainWindow/SaveDirectory"; + QSettings settings; + QString dir = settings.value(setting_name).toString(); + // Show the dialog const QString file_name = QFileDialog::getSaveFileName( - this, tr("Save File"), "", tr("Sigrok Sessions (*.sr)")); + this, tr("Save File"), dir, tr("Sigrok Sessions (*.sr)")); if (file_name.isEmpty()) return; + QString abs_path = QFileInfo(file_name).absolutePath(); + settings.setValue(setting_name, abs_path); + StoreProgress *dlg = new StoreProgress(file_name, _session, this); dlg->run(); } -- 1.9.0 |
From: Joel H. <jo...@ai...> - 2014-05-23 09:15:47
|
On 22/05/14 21:03, Jens Steinhauser wrote: > --- > main.cpp | 2 +- > pv/mainwindow.cpp | 25 ++++++++++++++++++++++--- > 2 files changed, 23 insertions(+), 4 deletions(-) > > diff --git a/main.cpp b/main.cpp > index 2c6a59e..5ff61d9 100644 > --- a/main.cpp > +++ b/main.cpp > @@ -69,7 +69,7 @@ int main(int argc, char *argv[]) > // Set some application metadata > QApplication::setApplicationVersion(PV_VERSION_STRING); > QApplication::setApplicationName("PulseView"); > - QApplication::setOrganizationDomain("http://www.sigrok.org"); > + QApplication::setOrganizationDomain("sigrok.org"); This should be split into a separate patch. > > // Parse arguments > while (1) { > diff --git a/pv/mainwindow.cpp b/pv/mainwindow.cpp > index 77e77a1..efb2f32 100644 > --- a/pv/mainwindow.cpp > +++ b/pv/mainwindow.cpp > @@ -35,6 +35,7 @@ > #include <QMessageBox> > #include <QMenu> > #include <QMenuBar> > +#include <QSettings> > #include <QStatusBar> > #include <QVBoxLayout> > #include <QWidget> > @@ -340,13 +341,23 @@ void MainWindow::show_session_error( > > void MainWindow::on_actionOpen_triggered() > { > + // Get the directory containing the last file that was opened > + const char* setting_name = "MainWindow/OpenDirectory"; > + QSettings settings; > + QString dir = settings.value(setting_name).toString(); > + > // Show the dialog > const QString file_name = QFileDialog::getOpenFileName( > - this, tr("Open File"), "", tr( > + this, tr("Open File"), dir, tr( > "Sigrok Sessions (*.sr);;" > "All Files (*.*)")); > - if (!file_name.isEmpty()) > + > + if (!file_name.isEmpty()) { > load_file(file_name); > + > + QString abs_path = QFileInfo(file_name).absolutePath(); > + settings.setValue(setting_name, abs_path); > + } > } > > void MainWindow::on_actionSaveAs_triggered() > @@ -356,13 +367,21 @@ void MainWindow::on_actionSaveAs_triggered() > // Stop any currently running capture session > _session.stop_capture(); > > + // Get the directory containing the last file that was saved > + const char* setting_name = "MainWindow/SaveDirectory"; > + QSettings settings; > + QString dir = settings.value(setting_name).toString(); > + QString dir = QSettings().value("MainWindow/SaveDirectory").toString(); is more concise. Or even const QString dir = QSettings().value("MainWindow/SaveDirectory").toString(); > // Show the dialog > const QString file_name = QFileDialog::getSaveFileName( > - this, tr("Save File"), "", tr("Sigrok Sessions (*.sr)")); > + this, tr("Save File"), dir, tr("Sigrok Sessions (*.sr)")); > > if (file_name.isEmpty()) > return; > > + QString abs_path = QFileInfo(file_name).absolutePath(); > + settings.setValue(setting_name, abs_path); > + > StoreProgress *dlg = new StoreProgress(file_name, _session, this); > dlg->run(); > } > |
From: Jens S. <jen...@gm...> - 2014-05-22 20:05:34
|
--- pv/mainwindow.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pv/mainwindow.cpp b/pv/mainwindow.cpp index efb2f32..95d2d56 100644 --- a/pv/mainwindow.cpp +++ b/pv/mainwindow.cpp @@ -256,10 +256,12 @@ void MainWindow::setup_ui() // Setup the toolbar QToolBar *const toolbar = new QToolBar(tr("Main Toolbar"), this); toolbar->addAction(action_open); + toolbar->addAction(action_save_as); toolbar->addSeparator(); toolbar->addAction(action_view_zoom_in); toolbar->addAction(action_view_zoom_out); toolbar->addAction(action_view_zoom_fit); + toolbar->addAction(action_view_zoom_one_to_one); addToolBar(toolbar); // Setup the sampling bar -- 1.9.0 |
From: Jens S. <jen...@gm...> - 2014-05-22 20:05:38
|
--- pv/mainwindow.cpp | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/pv/mainwindow.cpp b/pv/mainwindow.cpp index 95d2d56..b6f2706 100644 --- a/pv/mainwindow.cpp +++ b/pv/mainwindow.cpp @@ -44,6 +44,7 @@ #include "devicemanager.h" #include "device/device.h" +#include "device/file.h" #include "dialogs/about.h" #include "dialogs/connect.h" #include "dialogs/storeprogress.h" @@ -62,6 +63,7 @@ #include <glib.h> #include <libsigrok/libsigrok.h> +using boost::dynamic_pointer_cast; using boost::shared_ptr; using std::list; @@ -473,7 +475,19 @@ void MainWindow::run_stop() void MainWindow::capture_state_changed(int state) { - _sampling_bar->set_capture_state((pv::SigSession::capture_state)state); + pv::SigSession::capture_state s = (pv::SigSession::capture_state)state; + + _sampling_bar->set_capture_state(s); + + // Zoom fit if we opened a capture file + // + // It would be better to set the zoom level before loading the file, + // but until that is possible this does the job (see bug #236). + if (pv::SigSession::Stopped == s) { + if (dynamic_pointer_cast<pv::device::File>(_session.get_device())) { + _view->zoom_fit(); + } + } } } // namespace pv -- 1.9.0 |
From: Joel H. <jo...@ai...> - 2014-05-23 09:27:24
|
On 22/05/14 21:03, Jens Steinhauser wrote: > --- > pv/mainwindow.cpp | 16 +++++++++++++++- > 1 file changed, 15 insertions(+), 1 deletion(-) > > diff --git a/pv/mainwindow.cpp b/pv/mainwindow.cpp > index 95d2d56..b6f2706 100644 > --- a/pv/mainwindow.cpp > +++ b/pv/mainwindow.cpp > @@ -44,6 +44,7 @@ > > #include "devicemanager.h" > #include "device/device.h" > +#include "device/file.h" > #include "dialogs/about.h" > #include "dialogs/connect.h" > #include "dialogs/storeprogress.h" > @@ -62,6 +63,7 @@ > #include <glib.h> > #include <libsigrok/libsigrok.h> > > +using boost::dynamic_pointer_cast; > using boost::shared_ptr; > using std::list; > > @@ -473,7 +475,19 @@ void MainWindow::run_stop() > > void MainWindow::capture_state_changed(int state) > { > - _sampling_bar->set_capture_state((pv::SigSession::capture_state)state); > + pv::SigSession::capture_state s = (pv::SigSession::capture_state)state; > + > + _sampling_bar->set_capture_state(s); > + > + // Zoom fit if we opened a capture file > + // > + // It would be better to set the zoom level before loading the file, > + // but until that is possible this does the job (see bug #236). > + if (pv::SigSession::Stopped == s) { > + if (dynamic_pointer_cast<pv::device::File>(_session.get_device())) { > + _view->zoom_fit(); > + } > + } > } > > } // namespace pv > The problem with this is that it resizes the screen every time you reload the file by clicking "Run". This will be more important for the FPGA Simulation VCD file use case. In this case you might be zoomed in on some detail, and then reloading will take you back to the global view. Als we might want to use inotify to detect when the file gets rewritten by the simulator, or even just if the user presses "Run" to do the reload manually. We really only want it to auto scale the first load. I think the best solution may be to define a new signal handler slot in MainWindow: "on_file_first_loaded" or similar. Then connect this signal when MainWindow::load_file is called, and disconnect the signal when MainWindow::on_file_first_loaded first triggers. This way you get a single event notification when the file is first loaded, and you can set the zoom in there. Doing it this way means there's no need for an extra boolean member variable to indicate whether we're doing the first load, and it also means there's no need for dynamic_pointer_cast. The only problem with this is that I'm not sure what the best thing to trigger this signal would be. It could be triggered in MainWindow::capture_state_changed, but we'd still need a dynamic_pointer_cast in the case. Joel |
From: Jens S. <jen...@gm...> - 2014-05-22 20:05:42
|
--- pv/sigsession.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pv/sigsession.cpp b/pv/sigsession.cpp index b441dab..5ba2e5d 100644 --- a/pv/sigsession.cpp +++ b/pv/sigsession.cpp @@ -120,8 +120,8 @@ void SigSession::set_device( void SigSession::set_file(const string &name) throw(QString) { - // Deslect the old device, because file type detection in File::create - // destorys the old session inside libsigrok. + // Deselect the old device, because file type detection in File::create + // destroys the old session inside libsigrok. set_device(shared_ptr<device::DevInst>()); set_device(shared_ptr<device::DevInst>(device::File::create(name))); } -- 1.9.0 |
From: Jens S. <jen...@gm...> - 2014-05-22 20:05:42
|
--- pv/toolbars/samplingbar.cpp | 28 ++++++++++++++++++++++++++++ pv/toolbars/samplingbar.h | 3 +++ 2 files changed, 31 insertions(+) diff --git a/pv/toolbars/samplingbar.cpp b/pv/toolbars/samplingbar.cpp index 91c4b07..05c730b 100644 --- a/pv/toolbars/samplingbar.cpp +++ b/pv/toolbars/samplingbar.cpp @@ -26,6 +26,8 @@ #include <QAction> #include <QDebug> +#include <QHelpEvent> +#include <QToolTip> #include "samplingbar.h" @@ -93,6 +95,9 @@ SamplingBar::SamplingBar(SigSession &session, QWidget *parent) : addWidget(&_sample_rate); addWidget(&_run_stop_button); + + _sample_count.installEventFilter(this); + _sample_rate.installEventFilter(this); } void SamplingBar::set_device_list( @@ -446,5 +451,28 @@ void SamplingBar::on_config_changed() update_sample_rate_selector(); } +bool SamplingBar::eventFilter(QObject *watched, QEvent *event) +{ + if ((watched == &_sample_count || watched == &_sample_rate) && + (event->type() == QEvent::ToolTip)) { + double sec = (double)_sample_count.value() / _sample_rate.value(); + + QString str; + QTextStream(&str) + << tr("Total sampling time: ") + << fixed + << qSetRealNumberPrecision(1) + << sec + << "s"; + + QHelpEvent *help_event = static_cast<QHelpEvent*>(event); + QToolTip::showText(help_event->globalPos(), str); + + return true; + } + + return false; +} + } // namespace toolbars } // namespace pv diff --git a/pv/toolbars/samplingbar.h b/pv/toolbars/samplingbar.h index e59d2f9..e2e24b7 100644 --- a/pv/toolbars/samplingbar.h +++ b/pv/toolbars/samplingbar.h @@ -89,6 +89,9 @@ private slots: void on_config_changed(); +protected: + bool eventFilter(QObject *watched, QEvent *event); + private: SigSession &_session; -- 1.9.0 |
From: Jens S. <jen...@gm...> - 2014-05-22 20:05:43
|
--- CMakeLists.txt | 1 + pv/util.cpp | 59 ++++++++++++++++++++++++++++++++++++++++++++++++++ pv/util.h | 50 ++++++++++++++++++++++++++++++++++++++++++ pv/view/cursor.cpp | 6 ++--- pv/view/cursorpair.cpp | 6 ++--- pv/view/ruler.cpp | 30 ++++--------------------- pv/view/ruler.h | 6 ----- 7 files changed, 120 insertions(+), 38 deletions(-) create mode 100644 pv/util.cpp create mode 100644 pv/util.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 50dde49..a6a6c40 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -121,6 +121,7 @@ set(pulseview_SOURCES pv/mainwindow.cpp pv/sigsession.cpp pv/storesession.cpp + pv/util.cpp pv/data/analog.cpp pv/data/analogsnapshot.cpp pv/data/logic.cpp diff --git a/pv/util.cpp b/pv/util.cpp new file mode 100644 index 0000000..28e0dfd --- /dev/null +++ b/pv/util.cpp @@ -0,0 +1,59 @@ +/* + * This file is part of the PulseView project. + * + * Copyright (C) 2012 Joel Holdsworth <jo...@ai...> + * + * 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 "util.h" + +#include <extdef.h> + +#include <assert.h> + +#include <QTextStream> +#include <QDebug> + +using namespace Qt; + +namespace pv { +namespace util { + +static const QString SIPrefixes[9] = + {"f", "p", "n", QChar(0x03BC), "m", "", "k", "M", "G"}; +const int FirstSIPrefixPower = -15; + +QString format_time(double t, unsigned int prefix, + unsigned int precision, bool sign) +{ + assert(prefix < countof(SIPrefixes)); + + const double multiplier = pow(10.0, + (int)- prefix * 3 - FirstSIPrefixPower); + + QString s; + QTextStream ts(&s); + if (sign) { + ts << forcesign; + } + ts << fixed << qSetRealNumberPrecision(precision) + << (t * multiplier) << SIPrefixes[prefix] << "s"; + + return s; +} + +} // namespace util +} // namespace pv diff --git a/pv/util.h b/pv/util.h new file mode 100644 index 0000000..1af3ce9 --- /dev/null +++ b/pv/util.h @@ -0,0 +1,50 @@ +/* + * This file is part of the PulseView project. + * + * Copyright (C) 2012 Joel Holdsworth <jo...@ai...> + * + * 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 PULSEVIEW_UTIL_H +#define PULSEVIEW_UTIL_H + +#include <math.h> + +#include <QString> + +namespace pv { +namespace util { + +extern const int FirstSIPrefixPower; + +/** + * Formats a given time value with the specified SI prefix. + * @param t The time value in seconds to format. + * @param prefix The number of the prefix, from 0 for 'femto' up to + * 8 for 'giga'. + * @parma precision The number of digits after the decimal separator. + * @param sign Whether or not to add a sign also for positive numbers. + * + * @return The formated value. + */ +QString format_time( + double t, unsigned int prefix, + unsigned precision = 0, bool sign = true); + +} // namespace util +} // namespace pv + +#endif // PULSEVIEW_UTIL_H diff --git a/pv/view/cursor.cpp b/pv/view/cursor.cpp index ca22eef..95134b7 100644 --- a/pv/view/cursor.cpp +++ b/pv/view/cursor.cpp @@ -20,8 +20,8 @@ #include "cursor.h" -#include "ruler.h" #include "view.h" +#include "pv/util.h" #include <QBrush> #include <QPainter> @@ -139,13 +139,13 @@ void Cursor::paint_label(QPainter &p, const QRect &rect, p.setPen(TextColour); p.drawText(r, Qt::AlignCenter | Qt::AlignVCenter, - Ruler::format_time(_time, prefix, 2)); + pv::util::format_time(_time, prefix, 2)); } void Cursor::compute_text_size(QPainter &p, unsigned int prefix) { _text_size = p.boundingRect(QRectF(), 0, - Ruler::format_time(_time, prefix, 2)).size(); + pv::util::format_time(_time, prefix, 2)).size(); } shared_ptr<Cursor> Cursor::get_other_cursor() const diff --git a/pv/view/cursorpair.cpp b/pv/view/cursorpair.cpp index ed8829d..f73567e 100644 --- a/pv/view/cursorpair.cpp +++ b/pv/view/cursorpair.cpp @@ -20,8 +20,8 @@ #include "cursorpair.h" -#include "ruler.h" #include "view.h" +#include "pv/util.h" #include <algorithm> @@ -99,7 +99,7 @@ void CursorPair::draw_markers(QPainter &p, p.setPen(Cursor::TextColour); p.drawText(text_rect, Qt::AlignCenter | Qt::AlignVCenter, - Ruler::format_time(_second->time() - _first->time(), prefix, 2)); + pv::util::format_time(_second->time() - _first->time(), prefix, 2)); } // Paint the cursor markers @@ -137,7 +137,7 @@ void CursorPair::compute_text_size(QPainter &p, unsigned int prefix) assert(_first); assert(_second); - _text_size = p.boundingRect(QRectF(), 0, Ruler::format_time( + _text_size = p.boundingRect(QRectF(), 0, pv::util::format_time( _second->time() - _first->time(), prefix, 2)).size(); } diff --git a/pv/view/ruler.cpp b/pv/view/ruler.cpp index aec3de9..9e29ec2 100644 --- a/pv/view/ruler.cpp +++ b/pv/view/ruler.cpp @@ -23,13 +23,10 @@ #include "cursor.h" #include "view.h" #include "viewport.h" +#include "pv/util.h" #include <extdef.h> -#include <assert.h> -#include <math.h> -#include <limits.h> - #include <QApplication> #include <QMouseEvent> #include <QPainter> @@ -47,10 +44,6 @@ const int Ruler::RulerHeight = 30; const int Ruler::MinorTickSubdivision = 4; const int Ruler::ScaleUnits[3] = {1, 2, 5}; -const QString Ruler::SIPrefixes[9] = - {"f", "p", "n", QChar(0x03BC), "m", "", "k", "M", "G"}; -const int Ruler::FirstSIPrefixPower = -15; - const int Ruler::HoverArrowSize = 5; Ruler::Ruler(View &parent) : @@ -71,19 +64,6 @@ void Ruler::clear_selection() update(); } -QString Ruler::format_time(double t, unsigned int prefix, - unsigned int precision) -{ - const double multiplier = pow(10.0, - (int)- prefix * 3 - FirstSIPrefixPower); - - QString s; - QTextStream ts(&s); - ts.setRealNumberPrecision(precision); - ts << fixed << forcesign << (t * multiplier) << - SIPrefixes[prefix] << "s"; - return s; -} QSize Ruler::sizeHint() const { @@ -120,12 +100,10 @@ void Ruler::paintEvent(QPaintEvent*) tick_period = order_decimal * ScaleUnits[unit++]; } while (tick_period < min_period && unit < countof(ScaleUnits)); - prefix = (order - FirstSIPrefixPower) / 3; - assert(prefix < countof(SIPrefixes)); - + prefix = (order - pv::util::FirstSIPrefixPower) / 3; typical_width = p.boundingRect(0, 0, INT_MAX, INT_MAX, - AlignLeft | AlignTop, format_time(_view.offset(), + AlignLeft | AlignTop, pv::util::format_time(_view.offset(), prefix)).width() + MinValueSpacing; min_width += SpacingIncrement; @@ -163,7 +141,7 @@ void Ruler::paintEvent(QPaintEvent*) // Draw a major tick p.drawText(x, ValueMargin, 0, text_height, AlignCenter | AlignTop | TextDontClip, - format_time(t, prefix)); + pv::util::format_time(t, prefix)); p.drawLine(QPointF(x, major_tick_y1), QPointF(x, tick_y2)); } diff --git a/pv/view/ruler.h b/pv/view/ruler.h index dc4e7bb..c48f25a 100644 --- a/pv/view/ruler.h +++ b/pv/view/ruler.h @@ -40,9 +40,6 @@ private: static const int MinorTickSubdivision; static const int ScaleUnits[3]; - static const QString SIPrefixes[9]; - static const int FirstSIPrefixPower; - static const int HoverArrowSize; public: @@ -50,9 +47,6 @@ public: void clear_selection(); - static QString format_time(double t, unsigned int prefix, - unsigned precision = 0); - public: QSize sizeHint() const; -- 1.9.0 |
From: Jens S. <jen...@gm...> - 2014-05-22 20:05:46
|
This way the cursor labels don't overlap with the ruler. --- CMakeLists.txt | 2 + pv/view/cursorheader.cpp | 132 +++++++++++++++++++++++++++++++++++++++++++++++ pv/view/cursorheader.h | 64 +++++++++++++++++++++++ pv/view/marginwidget.cpp | 4 ++ pv/view/marginwidget.h | 2 +- pv/view/ruler.cpp | 90 +------------------------------- pv/view/ruler.h | 14 ----- pv/view/view.cpp | 32 ++++++++---- pv/view/view.h | 2 + 9 files changed, 228 insertions(+), 114 deletions(-) create mode 100644 pv/view/cursorheader.cpp create mode 100644 pv/view/cursorheader.h diff --git a/CMakeLists.txt b/CMakeLists.txt index a6a6c40..0016071 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -149,6 +149,7 @@ set(pulseview_SOURCES pv/toolbars/samplingbar.cpp pv/view/analogsignal.cpp pv/view/cursor.cpp + pv/view/cursorheader.cpp pv/view/cursorpair.cpp pv/view/header.cpp pv/view/marginwidget.cpp @@ -188,6 +189,7 @@ set(pulseview_HEADERS pv/prop/string.h pv/toolbars/samplingbar.h pv/view/cursor.h + pv/view/cursorheader.h pv/view/header.h pv/view/logicsignal.h pv/view/marginwidget.h diff --git a/pv/view/cursorheader.cpp b/pv/view/cursorheader.cpp new file mode 100644 index 0000000..2092466 --- /dev/null +++ b/pv/view/cursorheader.cpp @@ -0,0 +1,132 @@ +/* + * This file is part of the PulseView project. + * + * Copyright (C) 2012 Joel Holdsworth <jo...@ai...> + * + * 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 "cursorheader.h" + +#include "view.h" + +#include <QApplication> +#include <QMouseEvent> + +#include <pv/widgets/popup.h> + +using boost::shared_ptr; + +namespace pv { +namespace view { + +const int CursorHeader::CursorHeaderHeight = 26; + +CursorHeader::CursorHeader(View &parent) : + MarginWidget(parent), + _dragging(false) +{ + setMouseTracking(true); + + QPalette pal(palette()); + pal.setColor(QPalette::Window, Qt::white); + setPalette(pal); + setAutoFillBackground(true); +} + +QSize CursorHeader::sizeHint() const +{ + return QSize(0, CursorHeaderHeight); +} + +void CursorHeader::clear_selection() +{ + CursorPair &cursors = _view.cursors(); + cursors.first()->select(false); + cursors.second()->select(false); + update(); +} + +void CursorHeader::paintEvent(QPaintEvent*) +{ + QPainter p(this); + p.setRenderHint(QPainter::Antialiasing); + + // Draw the cursors + if (_view.cursors_shown()) { + _view.cursors().draw_markers(p, rect(), 0); //prefix); + } +} + +void CursorHeader::mouseMoveEvent(QMouseEvent *e) +{ + if (!(e->buttons() & Qt::LeftButton)) + return; + + if ((e->pos() - _mouse_down_point).manhattanLength() < + QApplication::startDragDistance()) + return; + + _dragging = true; + + if (shared_ptr<TimeMarker> m = _grabbed_marker.lock()) + m->set_time(_view.offset() + + ((double)e->x() + 0.5) * _view.scale()); +} + +void CursorHeader::mousePressEvent(QMouseEvent *e) +{ + if (e->buttons() & Qt::LeftButton) { + _mouse_down_point = e->pos(); + + _grabbed_marker.reset(); + + clear_selection(); + + if (_view.cursors_shown()) { + CursorPair &cursors = _view.cursors(); + if (cursors.first()->get_label_rect( + rect()).contains(e->pos())) + _grabbed_marker = cursors.first(); + else if (cursors.second()->get_label_rect( + rect()).contains(e->pos())) + _grabbed_marker = cursors.second(); + } + + if (shared_ptr<TimeMarker> m = _grabbed_marker.lock()) + m->select(); + + selection_changed(); + } +} + +void CursorHeader::mouseReleaseEvent(QMouseEvent *) +{ + using pv::widgets::Popup; + + if (!_dragging) + if (shared_ptr<TimeMarker> m = _grabbed_marker.lock()) { + Popup *const p = m->create_popup(&_view); + p->set_position(mapToGlobal(QPoint(m->get_x(), + height())), Popup::Bottom); + p->show(); + } + + _dragging = false; + _grabbed_marker.reset(); +} + +} // namespace view +} // namespace pv diff --git a/pv/view/cursorheader.h b/pv/view/cursorheader.h new file mode 100644 index 0000000..138925d --- /dev/null +++ b/pv/view/cursorheader.h @@ -0,0 +1,64 @@ +/* + * This file is part of the PulseView project. + * + * Copyright (C) 2012 Joel Holdsworth <jo...@ai...> + * + * 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 PULSEVIEW_PV_VIEW_CURSORHEADER_H +#define PULSEVIEW_PV_VIEW_CURSORHEADER_H + +#include <boost/weak_ptr.hpp> + +#include "marginwidget.h" + +namespace pv { +namespace view { + +class TimeMarker; + +/** + * Widget to hold the labels over the cursors. + */ +class CursorHeader : public MarginWidget +{ + Q_OBJECT + +public: + CursorHeader(View &parent); + + QSize sizeHint() const; + + void clear_selection(); + +private: + void paintEvent(QPaintEvent *event); + + void mouseMoveEvent(QMouseEvent *e); + void mousePressEvent(QMouseEvent *e); + void mouseReleaseEvent(QMouseEvent *); + + static const int CursorHeaderHeight; + + boost::weak_ptr<TimeMarker> _grabbed_marker; + QPoint _mouse_down_point; + bool _dragging; +}; + +} // namespace view +} // namespace pv + +#endif // PULSEVIEW_PV_VIEW_CURSORHEADER_H diff --git a/pv/view/marginwidget.cpp b/pv/view/marginwidget.cpp index 539551d..063dc9f 100644 --- a/pv/view/marginwidget.cpp +++ b/pv/view/marginwidget.cpp @@ -31,5 +31,9 @@ MarginWidget::MarginWidget(View &parent) : { } +void MarginWidget::clear_selection() +{ +} + } // namespace view } // namespace pv diff --git a/pv/view/marginwidget.h b/pv/view/marginwidget.h index 42dffa7..89eb3de 100644 --- a/pv/view/marginwidget.h +++ b/pv/view/marginwidget.h @@ -36,7 +36,7 @@ public: MarginWidget(pv::view::View &parent); public slots: - virtual void clear_selection() = 0; + virtual void clear_selection(); signals: void selection_changed(); diff --git a/pv/view/ruler.cpp b/pv/view/ruler.cpp index 9e29ec2..86f73f9 100644 --- a/pv/view/ruler.cpp +++ b/pv/view/ruler.cpp @@ -20,22 +20,12 @@ #include "ruler.h" -#include "cursor.h" #include "view.h" -#include "viewport.h" #include "pv/util.h" #include <extdef.h> -#include <QApplication> -#include <QMouseEvent> -#include <QPainter> -#include <QTextStream> - -#include <pv/widgets/popup.h> - using namespace Qt; -using boost::shared_ptr; namespace pv { namespace view { @@ -47,8 +37,7 @@ const int Ruler::ScaleUnits[3] = {1, 2, 5}; const int Ruler::HoverArrowSize = 5; Ruler::Ruler(View &parent) : - MarginWidget(parent), - _dragging(false) + MarginWidget(parent) { setMouseTracking(true); @@ -56,15 +45,6 @@ Ruler::Ruler(View &parent) : this, SLOT(hover_point_changed())); } -void Ruler::clear_selection() -{ - CursorPair &cursors = _view.cursors(); - cursors.first()->select(false); - cursors.second()->select(false); - update(); -} - - QSize Ruler::sizeHint() const { return QSize(0, RulerHeight); @@ -72,7 +52,6 @@ QSize Ruler::sizeHint() const void Ruler::paintEvent(QPaintEvent*) { - const double SpacingIncrement = 32.0f; const double MinValueSpacing = 32.0f; const int ValueMargin = 3; @@ -156,80 +135,15 @@ void Ruler::paintEvent(QPaintEvent*) } while (x < width()); - // Draw the cursors - if (_view.cursors_shown()) - _view.cursors().draw_markers(p, rect(), prefix); - // Draw the hover mark draw_hover_mark(p); - - p.end(); -} - -void Ruler::mouseMoveEvent(QMouseEvent *e) -{ - if (!(e->buttons() & Qt::LeftButton)) - return; - - if ((e->pos() - _mouse_down_point).manhattanLength() < - QApplication::startDragDistance()) - return; - - _dragging = true; - - if (shared_ptr<TimeMarker> m = _grabbed_marker.lock()) - m->set_time(_view.offset() + - ((double)e->x() + 0.5) * _view.scale()); -} - -void Ruler::mousePressEvent(QMouseEvent *e) -{ - if (e->buttons() & Qt::LeftButton) - { - _mouse_down_point = e->pos(); - - _grabbed_marker.reset(); - - clear_selection(); - - if (_view.cursors_shown()) { - CursorPair &cursors = _view.cursors(); - if (cursors.first()->get_label_rect( - rect()).contains(e->pos())) - _grabbed_marker = cursors.first(); - else if (cursors.second()->get_label_rect( - rect()).contains(e->pos())) - _grabbed_marker = cursors.second(); - } - - if (shared_ptr<TimeMarker> m = _grabbed_marker.lock()) - m->select(); - - selection_changed(); - } -} - -void Ruler::mouseReleaseEvent(QMouseEvent *) -{ - using pv::widgets::Popup; - - if (!_dragging) - if (shared_ptr<TimeMarker> m = _grabbed_marker.lock()) { - Popup *const p = m->create_popup(&_view); - p->set_position(mapToGlobal(QPoint(m->get_x(), - height())), Popup::Bottom); - p->show(); - } - - _dragging = false; - _grabbed_marker.reset(); } void Ruler::draw_hover_mark(QPainter &p) { const int x = _view.hover_point().x(); - if (x == -1 || _dragging) + if (x == -1) return; p.setPen(QPen(Qt::NoPen)); diff --git a/pv/view/ruler.h b/pv/view/ruler.h index c48f25a..93d7244 100644 --- a/pv/view/ruler.h +++ b/pv/view/ruler.h @@ -28,9 +28,6 @@ namespace pv { namespace view { -class TimeMarker; -class View; - class Ruler : public MarginWidget { Q_OBJECT @@ -45,18 +42,12 @@ private: public: Ruler(View &parent); - void clear_selection(); - public: QSize sizeHint() const; private: void paintEvent(QPaintEvent *event); - void mouseMoveEvent(QMouseEvent *e); - void mousePressEvent(QMouseEvent *e); - void mouseReleaseEvent(QMouseEvent *); - private: /** * Draw a hover arrow under the cursor position. @@ -65,11 +56,6 @@ private: private slots: void hover_point_changed(); - -private: - boost::weak_ptr<TimeMarker> _grabbed_marker; - QPoint _mouse_down_point; - bool _dragging; }; } // namespace view diff --git a/pv/view/view.cpp b/pv/view/view.cpp index d117489..f3d46b7 100644 --- a/pv/view/view.cpp +++ b/pv/view/view.cpp @@ -32,6 +32,7 @@ #include <QMouseEvent> #include <QScrollBar> +#include "cursorheader.h" #include "decodetrace.h" #include "header.h" #include "ruler.h" @@ -76,6 +77,7 @@ View::View(SigSession &session, QWidget *parent) : _session(session), _viewport(new Viewport(*this)), _ruler(new Ruler(*this)), + _cursorheader(new CursorHeader(*this)), _header(new Header(*this)), _scale(1e-6), _offset(0), @@ -108,19 +110,20 @@ View::View(SigSession &session, QWidget *parent) : this, SLOT(on_signals_moved())); connect(_header, SIGNAL(selection_changed()), - _ruler, SLOT(clear_selection())); - connect(_ruler, SIGNAL(selection_changed()), + _cursorheader, SLOT(clear_selection())); + connect(_cursorheader, SIGNAL(selection_changed()), _header, SLOT(clear_selection())); connect(_header, SIGNAL(selection_changed()), this, SIGNAL(selection_changed())); - connect(_ruler, SIGNAL(selection_changed()), + connect(_cursorheader, SIGNAL(selection_changed()), this, SIGNAL(selection_changed())); setViewport(_viewport); _viewport->installEventFilter(this); _ruler->installEventFilter(this); + _cursorheader->installEventFilter(this); _header->installEventFilter(this); // Trigger the initial event manually. The default device has signals @@ -215,6 +218,7 @@ void View::set_scale_offset(double scale, double offset) update_scroll(); _ruler->update(); + _cursorheader->update(); _viewport->update(); scale_offset_changed(); } @@ -307,7 +311,7 @@ bool View::cursors_shown() const void View::show_cursors(bool show) { _show_cursors = show; - _ruler->update(); + _cursorheader->update(); _viewport->update(); } @@ -316,7 +320,7 @@ void View::centre_cursors() const double time_width = _scale * _viewport->width(); _cursors.first()->set_time(_offset + time_width * 0.4); _cursors.second()->set_time(_offset + time_width * 0.6); - _ruler->update(); + _cursorheader->update(); _viewport->update(); } @@ -408,10 +412,15 @@ void View::update_scroll() void View::update_layout() { setViewportMargins(_header->sizeHint().width(), - _ruler->sizeHint().height(), 0, 0); - _ruler->setGeometry(_viewport->x(), 0, - _viewport->width(), _viewport->y()); - _header->setGeometry(0, _viewport->y(), + _ruler->sizeHint().height() + _cursorheader->sizeHint().height() - 1, 0, 0); + _ruler->setGeometry( + _viewport->x(), 0, + _viewport->width(), _ruler->sizeHint().height()); + _cursorheader->setGeometry( + _viewport->x(), _ruler->height(), + _viewport->width(), _cursorheader->sizeHint().height()); + _header->setGeometry( + 0, _viewport->y(), _viewport->x(), _viewport->height()); update_scroll(); } @@ -432,7 +441,7 @@ bool View::eventFilter(QObject *object, QEvent *event) const QMouseEvent *const mouse_event = (QMouseEvent*)event; if (object == _viewport) _hover_point = mouse_event->pos(); - else if (object == _ruler) + else if (object == _ruler || object == _cursorheader) _hover_point = QPoint(mouse_event->x(), 0); else if (object == _header) _hover_point = QPoint(0, mouse_event->y()); @@ -485,6 +494,7 @@ void View::h_scroll_value_changed(int value) } _ruler->update(); + _cursorheader->update(); _viewport->update(); } @@ -520,7 +530,7 @@ void View::data_updated() void View::marker_time_changed() { - _ruler->update(); + _cursorheader->update(); _viewport->update(); } diff --git a/pv/view/view.h b/pv/view/view.h index 0661637..653d947 100644 --- a/pv/view/view.h +++ b/pv/view/view.h @@ -42,6 +42,7 @@ class SigSession; namespace view { +class CursorHeader; class Header; class Ruler; class Trace; @@ -191,6 +192,7 @@ private: Viewport *_viewport; Ruler *_ruler; + CursorHeader *_cursorheader; Header *_header; /// The view time scale in seconds per pixel. -- 1.9.0 |
From: Jens S. <jen...@gm...> - 2014-05-22 20:05:48
|
--- pv/view/cursorheader.cpp | 6 ++++- pv/view/ruler.cpp | 70 +++++++++++++++++++++++++++--------------------- pv/view/ruler.h | 12 +++++++++ 3 files changed, 57 insertions(+), 31 deletions(-) diff --git a/pv/view/cursorheader.cpp b/pv/view/cursorheader.cpp index 8dcb38d..ced09d1 100644 --- a/pv/view/cursorheader.cpp +++ b/pv/view/cursorheader.cpp @@ -20,6 +20,7 @@ #include "cursorheader.h" +#include "ruler.h" #include "view.h" #include <QApplication> @@ -71,9 +72,12 @@ void CursorHeader::paintEvent(QPaintEvent*) QPainter p(this); p.setRenderHint(QPainter::Antialiasing); + unsigned int prefix = pv::view::Ruler::calculate_tick_spacing( + p, _view.scale(), _view.offset()).second; + // Draw the cursors if (_view.cursors_shown()) { - _view.cursors().draw_markers(p, rect(), 0); //prefix); + _view.cursors().draw_markers(p, rect(), prefix); } } diff --git a/pv/view/ruler.cpp b/pv/view/ruler.cpp index 86f73f9..3cc2eb1 100644 --- a/pv/view/ruler.cpp +++ b/pv/view/ruler.cpp @@ -52,42 +52,16 @@ QSize Ruler::sizeHint() const void Ruler::paintEvent(QPaintEvent*) { - const double SpacingIncrement = 32.0f; - const double MinValueSpacing = 32.0f; const int ValueMargin = 3; QPainter p(this); p.setRenderHint(QPainter::Antialiasing); - double min_width = SpacingIncrement, typical_width; - double tick_period; - unsigned int prefix; - - // Find tick spacing, and number formatting that does not cause - // value to collide. - do - { - const double min_period = _view.scale() * min_width; - - const int order = (int)floorf(log10f(min_period)); - const double order_decimal = pow(10.0, order); - - unsigned int unit = 0; - - do - { - tick_period = order_decimal * ScaleUnits[unit++]; - } while (tick_period < min_period && unit < countof(ScaleUnits)); - - prefix = (order - pv::util::FirstSIPrefixPower) / 3; + std::pair<double, unsigned int> spacing = + calculate_tick_spacing(p, _view.scale(), _view.offset()); - typical_width = p.boundingRect(0, 0, INT_MAX, INT_MAX, - AlignLeft | AlignTop, pv::util::format_time(_view.offset(), - prefix)).width() + MinValueSpacing; - - min_width += SpacingIncrement; - - } while(typical_width > tick_period / _view.scale()); + double tick_period = spacing.first; + unsigned int prefix = spacing.second; const int text_height = p.boundingRect(0, 0, INT_MAX, INT_MAX, AlignLeft | AlignTop, "8").height(); @@ -163,5 +137,41 @@ void Ruler::hover_point_changed() update(); } +std::pair<double, unsigned int> Ruler::calculate_tick_spacing( + QPainter& p, double scale, double offset) +{ + const double SpacingIncrement = 32.0f; + const double MinValueSpacing = 32.0f; + + double min_width = SpacingIncrement, typical_width; + + double tick_period; + unsigned int prefix; + + do { + const double min_period = scale * min_width; + + const int order = (int)floorf(log10f(min_period)); + const double order_decimal = pow(10.0, order); + + unsigned int unit = 0; + + do { + tick_period = order_decimal * ScaleUnits[unit++]; + } while (tick_period < min_period && unit < countof(ScaleUnits)); + + prefix = (order - pv::util::FirstSIPrefixPower) / 3; + + typical_width = p.boundingRect(0, 0, INT_MAX, INT_MAX, + AlignLeft | AlignTop, pv::util::format_time(offset, + prefix)).width() + MinValueSpacing; + + min_width += SpacingIncrement; + + } while(typical_width > tick_period / scale); + + return std::make_pair(tick_period, prefix); +} + } // namespace view } // namespace pv diff --git a/pv/view/ruler.h b/pv/view/ruler.h index 93d7244..2d173d2 100644 --- a/pv/view/ruler.h +++ b/pv/view/ruler.h @@ -42,6 +42,18 @@ private: public: Ruler(View &parent); + /** + * Find a tick spacing and number formatting that does not cause + * the values to collide. + * @param p A QPainter used to determine the needed space for the values. + * @param scale A pv::view::View's scale. + * @param offset A pv::view::View's offset. + * + * @return The tick period to use in 'first' and the prefix in 'second'. + */ + static std::pair<double, unsigned int> calculate_tick_spacing( + QPainter& p, double scale, double offset); + public: QSize sizeHint() const; -- 1.9.0 |
From: Jens S. <jen...@gm...> - 2014-05-22 20:05:50
|
--- pv/view/header.cpp | 11 +++++++---- pv/view/header.h | 2 +- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/pv/view/header.cpp b/pv/view/header.cpp index a790252..e7bfcbf 100644 --- a/pv/view/header.cpp +++ b/pv/view/header.cpp @@ -72,7 +72,10 @@ QSize Header::sizeHint() const const vector< shared_ptr<Trace> > traces(_view.get_traces()); BOOST_FOREACH(shared_ptr<Trace> t, traces) { assert(t); - max_width = max(max_width, (int)t->get_label_rect(0).width()); + + if (t->enabled()) { + max_width = max(max_width, (int)t->get_label_rect(0).width()); + } } return QSize(max_width + Padding, 0); @@ -281,9 +284,9 @@ void Header::on_signals_changed() BOOST_FOREACH(shared_ptr<Trace> t, traces) { assert(t); connect(t.get(), SIGNAL(visibility_changed()), - this, SLOT(update())); + this, SLOT(on_trace_changed())); connect(t.get(), SIGNAL(text_changed()), - this, SLOT(on_trace_text_changed())); + this, SLOT(on_trace_changed())); connect(t.get(), SIGNAL(colour_changed()), this, SLOT(update())); } @@ -294,7 +297,7 @@ void Header::on_signals_moved() update(); } -void Header::on_trace_text_changed() +void Header::on_trace_changed() { update(); geometry_updated(); diff --git a/pv/view/header.h b/pv/view/header.h index 5474f10..489a5ca 100644 --- a/pv/view/header.h +++ b/pv/view/header.h @@ -74,7 +74,7 @@ private slots: void on_signals_moved(); - void on_trace_text_changed(); + void on_trace_changed(); signals: void signals_moved(); -- 1.9.0 |
From: Jens S. <jen...@gm...> - 2014-05-22 20:05:58
|
--- pv/toolbars/samplingbar.cpp | 12 +++--------- pv/util.cpp | 13 +++++++++++++ pv/util.h | 9 +++++++++ 3 files changed, 25 insertions(+), 9 deletions(-) diff --git a/pv/toolbars/samplingbar.cpp b/pv/toolbars/samplingbar.cpp index 05c730b..085e043 100644 --- a/pv/toolbars/samplingbar.cpp +++ b/pv/toolbars/samplingbar.cpp @@ -35,6 +35,7 @@ #include <pv/device/devinst.h> #include <pv/popups/deviceoptions.h> #include <pv/popups/probes.h> +#include <pv/util.h> using boost::shared_ptr; using std::map; @@ -456,16 +457,9 @@ bool SamplingBar::eventFilter(QObject *watched, QEvent *event) if ((watched == &_sample_count || watched == &_sample_rate) && (event->type() == QEvent::ToolTip)) { double sec = (double)_sample_count.value() / _sample_rate.value(); - - QString str; - QTextStream(&str) - << tr("Total sampling time: ") - << fixed - << qSetRealNumberPrecision(1) - << sec - << "s"; - QHelpEvent *help_event = static_cast<QHelpEvent*>(event); + + QString str = tr("Total sampling time: %1").arg(pv::util::format_second(sec)); QToolTip::showText(help_event->globalPos(), str); return true; diff --git a/pv/util.cpp b/pv/util.cpp index 28e0dfd..a54bdca 100644 --- a/pv/util.cpp +++ b/pv/util.cpp @@ -55,5 +55,18 @@ QString format_time(double t, unsigned int prefix, return s; } +QString format_second(double second) +{ + unsigned int i = 0; + int exp = - FirstSIPrefixPower; + + while ((second * pow(10.0, exp)) > 999.0 && i < countof(SIPrefixes) - 1) { + i++; + exp -= 3; + } + + return format_time(second, i, 0, false); +} + } // namespace util } // namespace pv diff --git a/pv/util.h b/pv/util.h index 1af3ce9..572bed3 100644 --- a/pv/util.h +++ b/pv/util.h @@ -44,6 +44,15 @@ QString format_time( double t, unsigned int prefix, unsigned precision = 0, bool sign = true); +/** + * Formats a given time value with a SI prefix so that the + * value is between 1 and 999. + * @param second The time value in seconds to format. + * + * @return The formated value. + */ +QString format_second(double second); + } // namespace util } // namespace pv -- 1.9.0 |
From: Jens S. <jen...@gm...> - 2014-05-22 20:06:01
|
--- pv/view/view.cpp | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/pv/view/view.cpp b/pv/view/view.cpp index f3d46b7..4ee1f28 100644 --- a/pv/view/view.cpp +++ b/pv/view/view.cpp @@ -313,6 +313,7 @@ void View::show_cursors(bool show) _show_cursors = show; _cursorheader->update(); _viewport->update(); + update_layout(); } void View::centre_cursors() @@ -411,17 +412,25 @@ void View::update_scroll() void View::update_layout() { - setViewportMargins(_header->sizeHint().width(), - _ruler->sizeHint().height() + _cursorheader->sizeHint().height() - 1, 0, 0); + if (_show_cursors) { + setViewportMargins(_header->sizeHint().width(), + _ruler->sizeHint().height() + _cursorheader->sizeHint().height(), 0, 0); + _cursorheader->setGeometry( + _viewport->x(), _ruler->height() + 1, + _viewport->width(), _cursorheader->sizeHint().height()); + _cursorheader->setVisible(true); + } else { + setViewportMargins(_header->sizeHint().width(), + _ruler->sizeHint().height(), 0, 0); + _cursorheader->setVisible(false); + } _ruler->setGeometry( _viewport->x(), 0, _viewport->width(), _ruler->sizeHint().height()); - _cursorheader->setGeometry( - _viewport->x(), _ruler->height(), - _viewport->width(), _cursorheader->sizeHint().height()); _header->setGeometry( 0, _viewport->y(), _viewport->x(), _viewport->height()); + update_scroll(); } -- 1.9.0 |
From: Jens S. <jen...@gm...> - 2014-05-22 20:06:02
|
--- pv/view/cursorheader.cpp | 13 ++++++++++--- pv/view/cursorheader.h | 3 ++- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/pv/view/cursorheader.cpp b/pv/view/cursorheader.cpp index 2092466..8dcb38d 100644 --- a/pv/view/cursorheader.cpp +++ b/pv/view/cursorheader.cpp @@ -23,6 +23,7 @@ #include "view.h" #include <QApplication> +#include <QFontMetrics> #include <QMouseEvent> #include <pv/widgets/popup.h> @@ -32,11 +33,17 @@ using boost::shared_ptr; namespace pv { namespace view { -const int CursorHeader::CursorHeaderHeight = 26; +int CursorHeader::calculateTextHeight() +{ + QFontMetrics fm(font()); + return fm.boundingRect(0, 0, INT_MAX, INT_MAX, + Qt::AlignLeft | Qt::AlignTop, "8").height(); +} CursorHeader::CursorHeader(View &parent) : MarginWidget(parent), - _dragging(false) + _dragging(false), + _textHeight(calculateTextHeight()) { setMouseTracking(true); @@ -48,7 +55,7 @@ CursorHeader::CursorHeader(View &parent) : QSize CursorHeader::sizeHint() const { - return QSize(0, CursorHeaderHeight); + return QSize(0, _textHeight + 10); } void CursorHeader::clear_selection() diff --git a/pv/view/cursorheader.h b/pv/view/cursorheader.h index 138925d..15588b4 100644 --- a/pv/view/cursorheader.h +++ b/pv/view/cursorheader.h @@ -51,11 +51,12 @@ private: void mousePressEvent(QMouseEvent *e); void mouseReleaseEvent(QMouseEvent *); - static const int CursorHeaderHeight; + int calculateTextHeight(); boost::weak_ptr<TimeMarker> _grabbed_marker; QPoint _mouse_down_point; bool _dragging; + const int _textHeight; }; } // namespace view -- 1.9.0 |
From: Joel H. <jo...@ai...> - 2014-05-23 09:13:45
|
Hi Jens, It's really great to have your contributions. Thank you for getting involved! If you have time, I highly recommend joining us at #sigrok IRC on FreeNode. This is where most of the sigrok crowd gathers to discuss things. With regard to your patches, most of them are good to go in, I would say. I will reply with some inline comments in a couple of cases. The big thing I wanted to discuss was your CursorHeader. I guess you put this in because the cursor markers are covering the time markings on the ruler. It's a fair point. The current design certainly isn't ideal. My concern is that having the CursorHeader won't fit very well with the other things we need to consider. In the future cursors are not going to be the time only markers that will be displayed in the ruler. There will be the trigger point indicator, and there may be other kinds of marker up there. Flags for example? If there were a trigger marker or some other markers, the CursorHeader would have to be shown all the time. So why not just integrate it in into the ruler anyway? Adding extra bars is a kind of tax on screen space, and in this case there's not much payoff for this tax. On a large screen machine this is not going to be so critical (though we still want to try and cut it back), but on mobile we really need to minimize the width of borders that we add. Many scopes get around this by drawing the markers directly onto the canvas: http://goo.gl/17pDHG , http://goo.gl/NJkou3. But I think this may be a little too intrusive on the canvas, because our markers are rather larger. I was wondering whether we could have a compomise where the markers half-cover both: http://www.airwebreathe.org.uk/space/half-cover.png The way to do this would be to take your CursorHeader and make it a transparent widget that overlays both the ruler and the canvas. This would also allow us to get around the problem we have with the selection highlight where the highlight is clipped to the edge of the ruler widget. sigrok guys: Any thoughts? Jens: Any thoughts? Joel On 22/05/14 21:03, Jens Steinhauser wrote: > These patches add small changes for stuff that I found missing when using > PulseView, and others may find useful too. > > Jens Steinhauser (13): > MainWindow: Add shortcuts for the open/save menu items. > MainWindow: Remember directory of last file that was opened/saved. > MainWindow: Add missing toolbar buttons. > MainWindow: Zoom fit after opening a capature file. > SigSession: Fix typo in comment. > SamplingBar: Show total sampling time in a tooltip. > Put the time format function into a separate file. > SamplingBar: Use nicer time format in the tooltip. > Use a separate widget to hold the cursor labels. > View: Hide the cursorheader with the cursors. > CursorHeader: Make the size dependend on the used font. > CursorHeader: Use the same number format as the ruler. > Header: Invisible traces shouldn't influence the width. > > CMakeLists.txt | 3 + > main.cpp | 2 +- > pv/mainwindow.cpp | 45 ++++++++++- > pv/sigsession.cpp | 4 +- > pv/toolbars/samplingbar.cpp | 22 ++++++ > pv/toolbars/samplingbar.h | 3 + > pv/util.cpp | 72 +++++++++++++++++ > pv/util.h | 59 ++++++++++++++ > pv/view/cursor.cpp | 6 +- > pv/view/cursorheader.cpp | 143 ++++++++++++++++++++++++++++++++++ > pv/view/cursorheader.h | 65 ++++++++++++++++ > pv/view/cursorpair.cpp | 6 +- > pv/view/header.cpp | 11 ++- > pv/view/header.h | 2 +- > pv/view/marginwidget.cpp | 4 + > pv/view/marginwidget.h | 2 +- > pv/view/ruler.cpp | 186 +++++++++++--------------------------------- > pv/view/ruler.h | 30 +++---- > pv/view/view.cpp | 43 +++++++--- > pv/view/view.h | 2 + > 20 files changed, 518 insertions(+), 192 deletions(-) > create mode 100644 pv/util.cpp > create mode 100644 pv/util.h > create mode 100644 pv/view/cursorheader.cpp > create mode 100644 pv/view/cursorheader.h > |
From: Rasz <cit...@gm...> - 2014-06-02 07:38:06
|
On 5/23/14, Joel Holdsworth <jo...@ai...> wrote: > Adding extra bars is a kind of tax on screen space, and in this case > there's not much payoff for this tax. On a large screen machine this is > not going to be so critical (though we still want to try and cut it > back), but on mobile we really need to minimize the width of borders > that we add. Please dont castrate good UI in the name of supporting mobile. Look what happened to Microsoft (or Gnome) when they forced mobile constraints on desktop users. Add customizability instead of limiting usability. > Many scopes get around this by drawing the markers directly onto the > canvas: http://goo.gl/17pDHG , http://goo.gl/NJkou3. But I think this > may be a little too intrusive on the canvas, because our markers are > rather larger. They dont have to be labelled. Simple triangle and a number/letter is enough. Provide separate panel/snap in window with list or markers. You will need one for Measurements anyway. -- Who logs in to gdm? Not I, said the duck. |