[LyX/master] Add document statistics to statusbar.

Pavel Sanda sanda at lyx.org
Tue Aug 9 21:04:36 UTC 2022


commit 5b50a97fd76d237dbf91fe897739dc4e11ee6551
Author: Pavel Sanda <sanda at lyx.org>
Date:   Tue Aug 9 23:48:55 2022 +0200

    Add document statistics to statusbar.
    
    https://www.mail-archive.com/lyx-devel@lists.lyx.org/msg217810.html
---
 lib/ui/stdcontext.inc        |    2 +
 src/LyXAction.cpp            |    1 +
 src/frontends/qt/GuiView.cpp |   93 +++++++++++++++++++++++++++++++++++++++++-
 src/frontends/qt/GuiView.h   |    6 +++
 4 files changed, 100 insertions(+), 2 deletions(-)

diff --git a/lib/ui/stdcontext.inc b/lib/ui/stdcontext.inc
index bd94e7c..402dbcd 100644
--- a/lib/ui/stdcontext.inc
+++ b/lib/ui/stdcontext.inc
@@ -731,6 +731,8 @@ Menuset
 		Separator
 		Item "Show Zoom Level|Z" "ui-toggle zoomlevel"
 		Item "Show Zoom Slider|S" "ui-toggle zoomslider"
+		Separator
+		Item "Show Statistics|D" "ui-toggle statistics"
 	End
 
 End
diff --git a/src/LyXAction.cpp b/src/LyXAction.cpp
index 992b47a..ae8245d 100644
--- a/src/LyXAction.cpp
+++ b/src/LyXAction.cpp
@@ -4097,6 +4097,7 @@ void LyXAction::init()
                frame      : Toggle visibility of the frames around editing window.\n
                zoomslider : Toggle visibility of the zoom slider in statusbar.\n
                zoomlevel  : Toggle visibility of the zoom level display in statusbar.\n
+               statistics : Toggle visibility of the document statistics count in statusbar.\n
                fullscreen : Toggle fullscreen mode. This also covers calling the
                             previous functions. However #LFUN_TOOLBAR_TOGGLE for the
                             custom tweaks of the toolbars should be used.
diff --git a/src/frontends/qt/GuiView.cpp b/src/frontends/qt/GuiView.cpp
index 8f6bf07..28c196d 100644
--- a/src/frontends/qt/GuiView.cpp
+++ b/src/frontends/qt/GuiView.cpp
@@ -523,6 +523,7 @@ public:
 
 	///
 	QTimer statusbar_timer_;
+	QTimer statusbar_stats_timer_;
 	/// auto-saving of buffers
 	Timeout autosave_timeout_;
 
@@ -546,6 +547,20 @@ public:
 
 	/// flag against a race condition due to multiclicks, see bug #1119
 	bool in_show_;
+
+	// Timers for statistic updates in buffer
+	/// Current time left to the nearest info update
+	int time_to_update = 1000;
+	///Basic step for timer in ms. Basically reaction time for short selections
+	int const timer_rate = 500;
+	/// Real stats updates infrequently. First they take long time for big buffers, second
+	/// they are visible for fast-repeat keyboards even for mid documents.
+	int const default_stats_rate = 5000;
+	/// Detection of new selection, so we can react fast
+	bool already_in_selection_ = false;
+	/// Maximum size of "short" selection for which we can update with faster timer_rate
+	int const max_sel_chars = 5000;
+
 };
 
 QSet<Buffer const *> GuiView::GuiViewPrivate::busyBuffers;
@@ -553,8 +568,8 @@ QSet<Buffer const *> GuiView::GuiViewPrivate::busyBuffers;
 
 GuiView::GuiView(int id)
 	: d(*new GuiViewPrivate(this)), id_(id), closing_(false), busy_(0),
-	  command_execute_(false), minibuffer_focus_(false), toolbarsMovable_(true),
-	  devel_mode_(false)
+	  command_execute_(false), minibuffer_focus_(false), stat_counts_enabled_(true),
+	  toolbarsMovable_(true), devel_mode_(false)
 {
 	connect(this, SIGNAL(bufferViewChanged()),
 	        this, SLOT(onBufferViewChanged()));
@@ -582,6 +597,9 @@ GuiView::GuiView(int id)
 	}
 	connect(&d.statusbar_timer_, SIGNAL(timeout()),
 		this, SLOT(clearMessage()));
+	connect(&d.statusbar_stats_timer_, SIGNAL(timeout()),
+		this, SLOT(showStats()));
+	d.statusbar_stats_timer_.start(d.timer_rate);
 
 	// We don't want to keep the window in memory if it is closed.
 	setAttribute(Qt::WA_DeleteOnClose, true);
@@ -627,6 +645,13 @@ GuiView::GuiView(int id)
 		busySVG, SLOT(hide()));
 	connect(busySVG, SIGNAL(pressed()), this, SLOT(checkCancelBackground()));
 
+	stat_counts_ = new QLabel(statusBar());
+	stat_counts_->setAlignment(Qt::AlignCenter);
+	stat_counts_->setFrameStyle(QFrame::StyledPanel);
+	stat_counts_->hide();
+	statusBar()->addPermanentWidget(stat_counts_);
+
+
 	QFontMetrics const fm(statusBar()->fontMetrics());
 
 	zoom_slider_ = new QSlider(Qt::Horizontal, statusBar());
@@ -952,6 +977,7 @@ void GuiView::saveLayout() const
 	settings.setValue("icon_size", toqstr(d.iconSize(iconSize())));
 	settings.setValue("zoom_value_visible", zoom_value_->isVisible());
 	settings.setValue("zoom_slider_visible", zoom_slider_->isVisible());
+	settings.setValue("document_stats_enabled", stat_counts_enabled_);
 }
 
 
@@ -1001,6 +1027,9 @@ bool GuiView::restoreLayout()
 	zoom_in_->setVisible(show_zoom_slider);
 	zoom_out_->setVisible(show_zoom_slider);
 
+	stat_counts_enabled_ = settings.value("document_stats_enabled", true).toBool();
+	stat_counts_->setVisible(stat_counts_enabled_);
+
 	if (guiApp->platformName() == "qt4x11" || guiApp->platformName() == "xcb") {
 		QPoint pos = settings.value("pos", QPoint(50, 50)).toPoint();
 		QSize size = settings.value("size", QSize(690, 510)).toSize();
@@ -1271,6 +1300,7 @@ void GuiView::closeEvent(QCloseEvent * close_event)
 
 	// Make sure the timer time out will not trigger a statusbar update.
 	d.statusbar_timer_.stop();
+	d.statusbar_stats_timer_.stop();
 
 	// Saving fullscreen requires additional tweaks in the toolbar code.
 	// It wouldn't also work under linux natively.
@@ -1376,6 +1406,60 @@ void GuiView::clearMessage()
 	d.statusbar_timer_.stop();
 }
 
+void GuiView::showStats()
+{
+	if (!stat_counts_enabled_)
+		return;
+
+
+	d.time_to_update -= d.timer_rate;
+
+	BufferView * bv = currentBufferView();
+	Buffer * buf = bv ? &bv->buffer() : nullptr;
+	if (buf) {
+
+		Cursor const & cur = bv->cursor();
+
+		//we start new selection and need faster update
+		if (!d.already_in_selection_ && cur.selection())
+			d.time_to_update = 0;
+
+		if (d.time_to_update <= 0) {
+
+			DocIterator from, to;
+
+			if (cur.selection()) {
+				from = cur.selectionBegin();
+				to = cur.selectionEnd();
+				d.already_in_selection_ = true;
+			} else {
+				from = doc_iterator_begin(buf);
+				to = doc_iterator_end(buf);
+				d.already_in_selection_ = false;
+			}
+
+			buf->updateStatistics(from, to);
+
+			int const words = buf->wordCount();
+			int const chars = buf->charCount(false);
+			int const chars_with_blanks = buf->charCount(true);
+
+			QString stats = toqstr(_("w:[[words]]")) + QString::number(words) + " " +
+				toqstr(_("c:[[characters]]")) +  QString::number(chars) + " " +
+				toqstr(_("cb:[[characters with blanks]]")) + QString::number(chars_with_blanks);
+			stat_counts_->setText(stats);
+			stat_counts_->show();
+
+			d.time_to_update = d.default_stats_rate;
+			//fast updates for small selections
+			if (chars_with_blanks < d.max_sel_chars && cur.selection())
+				d.time_to_update = d.timer_rate;
+		}
+
+	} else
+		stat_counts_->hide();
+}
+
 
 void GuiView::updateWindowTitle(GuiWorkArea * wa)
 {
@@ -2419,6 +2503,8 @@ bool GuiView::getStatus(FuncRequest const & cmd, FuncStatus & flag)
 			flag.setOnOff(zoom_value_ ? zoom_value_->isVisible() : false);
 		} else if (cmd.argument() == "zoomslider") {
 			flag.setOnOff(zoom_slider_ ? zoom_slider_->isVisible() : false);
+		} else if (cmd.argument() == "statistics") {
+			flag.setOnOff(stat_counts_enabled_);
 		} else
 			flag.setOnOff(isFullScreen());
 		break;
@@ -4904,6 +4990,9 @@ bool GuiView::lfunUiToggle(string const & ui_component)
 		zoom_slider_->setVisible(!zoom_slider_->isVisible());
 		zoom_in_->setVisible(zoom_slider_->isVisible());
 		zoom_out_->setVisible(zoom_slider_->isVisible());
+	} else if (ui_component == "statistics") {
+		stat_counts_enabled_ = !stat_counts_enabled_;
+		stat_counts_->setVisible(stat_counts_enabled_);
 	} else if (ui_component == "frame") {
 		int const l = contentsMargins().left();
 
diff --git a/src/frontends/qt/GuiView.h b/src/frontends/qt/GuiView.h
index 241701c..2f7c34e 100644
--- a/src/frontends/qt/GuiView.h
+++ b/src/frontends/qt/GuiView.h
@@ -235,6 +235,8 @@ public Q_SLOTS:
 	/// idle timeout.
 	/// clear any temporary message and replace with current status.
 	void clearMessage();
+	/// show documents stats in toolbar and trigger new iteration
+	void showStats();
 	///
 	void updateWindowTitle(GuiWorkArea * wa);
 	///
@@ -510,6 +512,10 @@ private:
 	QLabel * read_only_;
 	/// Statusbar widget that shows version control status
 	QLabel * version_control_;
+	/// Statusbar widget that document count statistics
+	QLabel * stat_counts_;
+	/// Stats info feature can be disabled by context menu
+	bool stat_counts_enabled_;
 	/// Statusbar widget that shows zoom value
 	QLabel * zoom_value_;
 	/// The zoom slider widget


More information about the lyx-cvs mailing list