From d17c86e8c52b6c8ae4ed276ace8727f0c9097bc4 Mon Sep 17 00:00:00 2001
From: n4hy <n4hy@221aa14e-8319-0410-a670-987f0aec2ac5>
Date: Wed, 21 Feb 2007 21:24:23 +0000
Subject: Beginnings of a qt based gui system added under gr-qtgui

git-svn-id: http://gnuradio.org/svn/gnuradio/trunk@4564 221aa14e-8319-0410-a670-987f0aec2ac5
---
 gr-qtgui/src/Makefile.am          |  24 ++++++
 gr-qtgui/src/lib/Makefile.am      |  60 +++++++++++++++
 gr-qtgui/src/lib/fftdisplay.cc    | 157 ++++++++++++++++++++++++++++++++++++++
 gr-qtgui/src/lib/fftdisplay.h     |  61 +++++++++++++++
 gr-qtgui/src/lib/fftdisplaysink.h |  16 ++++
 gr-qtgui/src/lib/qt_examples.cc   | 122 +++++++++++++++++++++++++++++
 6 files changed, 440 insertions(+)
 create mode 100644 gr-qtgui/src/Makefile.am
 create mode 100644 gr-qtgui/src/lib/Makefile.am
 create mode 100644 gr-qtgui/src/lib/fftdisplay.cc
 create mode 100644 gr-qtgui/src/lib/fftdisplay.h
 create mode 100644 gr-qtgui/src/lib/fftdisplaysink.h
 create mode 100644 gr-qtgui/src/lib/qt_examples.cc

(limited to 'gr-qtgui/src')

diff --git a/gr-qtgui/src/Makefile.am b/gr-qtgui/src/Makefile.am
new file mode 100644
index 0000000000..6e5c054bcf
--- /dev/null
+++ b/gr-qtgui/src/Makefile.am
@@ -0,0 +1,24 @@
+#
+# Copyright 2004 Free Software Foundation, Inc.
+# 
+# This file is part of GNU Radio
+# 
+# GNU Radio 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, or (at your option)
+# any later version.
+# 
+# GNU Radio 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 GNU Radio; see the file COPYING.  If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+# 
+
+include $(top_srcdir)/Makefile.common
+
+SUBDIRS = lib
diff --git a/gr-qtgui/src/lib/Makefile.am b/gr-qtgui/src/lib/Makefile.am
new file mode 100644
index 0000000000..2f98dd5d0f
--- /dev/null
+++ b/gr-qtgui/src/lib/Makefile.am
@@ -0,0 +1,60 @@
+#
+# Copyright 2004,2005 Free Software Foundation, Inc.
+# 
+# This file is part of GNU Radio
+# 
+# GNU Radio 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, or (at your option)
+# any later version.
+# 
+# GNU Radio 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 GNU Radio; see the file COPYING.  If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+# 
+
+include $(top_srcdir)/Makefile.common
+
+INCLUDES = $(STD_DEFINES_AND_INCLUDES)	\
+	   $(QT_CFLAGS)			\
+	   $(QWT_CFLAGS) 
+
+# This rule lets GNU create any moc_*.cc files from the equivalent *.h
+moc_%.cc: %.h
+	moc $< -o $@
+
+# Generate the .h and .cc files from the .ui file
+%.h: %.ui
+	uic $< -o $@
+
+%.cc: %.ui
+	uic -impl $*.h $< -o $@
+
+include_HEADERS =
+	fftdisplay.h			\
+	fftdisplaysink.h
+
+noinst_PROGRAMS = 			\
+	qt_examples	
+
+qt_examples_MOC =			\
+	moc_fftdisplay.cc
+
+qt_examples_SOURCES = 			\
+	fftdisplay.cc			\
+	qt_examples.cc			\
+	$(qt_examples_MOC)
+
+qt_examples_LDADD = $(QWT_LIBS) $(QT_LIBS)
+qt_examples_LDFLAGS = $(QT_CFLAGS) $(QWT_CFLAGS) $(GNURADIO_CORE_LIBS)
+
+MOSTLYCLEANFILES = 			\
+	*~
+
+CLEANFILES = $(filter moc_%.cc, $(qt_examples_SOURCES))		
diff --git a/gr-qtgui/src/lib/fftdisplay.cc b/gr-qtgui/src/lib/fftdisplay.cc
new file mode 100644
index 0000000000..d701642801
--- /dev/null
+++ b/gr-qtgui/src/lib/fftdisplay.cc
@@ -0,0 +1,157 @@
+#ifndef FFT_DISPLAY_CC
+#define FFT_DISPLAY_CC
+
+#include <qwt_painter.h>
+#include <qwt_plot_canvas.h>
+#include <qwt_plot_curve.h>
+#include <qwt_scale_engine.h>
+#include <qapplication.h>
+#include <fftdisplay.h>
+
+const int fft_display_event::EVENT_TYPE_ID = QEvent::User+100;
+
+fft_display_event::fft_display_event( std::vector<gr_complex>* fft_data, const float start_frequency, const float stop_frequency):QCustomEvent(fft_display_event::EVENT_TYPE_ID){
+	d_fft_data.resize(fft_data->size());
+	for(unsigned int i = 0; i < fft_data->size(); i++){
+		d_fft_data[i] = fft_data->operator[](i);
+	}
+	d_start_frequency = start_frequency;
+	d_stop_frequency = stop_frequency;
+}
+
+fft_display_event::~fft_display_event(){
+
+}
+
+const std::vector<gr_complex>& fft_display_event::get_fft_data() const{
+	return d_fft_data;
+}
+
+float fft_display_event::get_start_frequency()const{
+	return d_start_frequency;
+}
+
+float fft_display_event::get_stop_frequency()const{
+	return d_stop_frequency;
+}
+
+fft_display::fft_display(const unsigned int fft_size, QWidget* parent):
+	QwtPlot(parent)
+{
+    	// Disable polygon clipping
+    	QwtPainter::setDeviceClipping(false);
+
+    	// We don't need the cache here
+    	canvas()->setPaintAttribute(QwtPlotCanvas::PaintCached, false);
+    	canvas()->setPaintAttribute(QwtPlotCanvas::PaintPacked, false);
+
+	canvas()->setPaletteBackgroundColor(QColor("white"));
+
+	d_fft_bin_size = fft_size;
+	if(d_fft_bin_size < 1){
+		d_fft_bin_size = 1;
+	}
+
+	d_start_frequency = 0.0;
+	d_stop_frequency = 4000.0;
+
+	d_fft_data = new std::vector<gr_complex>(d_fft_bin_size);
+	d_plot_data = new double[d_fft_bin_size];
+	d_x_data = new double[d_fft_bin_size];
+	for( unsigned int i = 0; i < d_fft_bin_size; i++){
+		d_fft_data->operator[](i) = gr_complex(static_cast<float>(i), 0.0);
+		d_x_data[i] = d_start_frequency + ((d_stop_frequency-d_start_frequency) / static_cast<float>(d_fft_bin_size)*static_cast<float>(i));
+		d_plot_data[i] = 1.0;
+	}
+	
+	// Set the Appropriate Axis Scale Engine
+#warning Pass the axis info as necessary...
+	if(true){
+		setAxisScaleEngine(QwtPlot::yLeft, new QwtLinearScaleEngine);
+	}
+	else{
+		setAxisScaleEngine(QwtPlot::yLeft, new QwtLog10ScaleEngine);
+	}
+
+	QwtPlotCurve* fft_plot_curve = new QwtPlotCurve("FFT Spectrum");
+	fft_plot_curve->attach(this);
+	fft_plot_curve->setPen(QPen(Qt::blue));
+	fft_plot_curve->setRawData(d_x_data, d_plot_data, d_fft_bin_size);
+
+	setTitle("Spectral Display");
+}
+
+fft_display::~fft_display(){
+	/* The Qwt objects are destroyed by Qt when their parent is destroyed */
+
+	delete[] d_plot_data;
+	delete[] d_x_data;
+	delete d_fft_data;
+}
+
+
+void fft_display::set_data(const std::vector<gr_complex>& input_data){
+	unsigned int min_points = d_fft_data->size();
+	if(min_points < input_data.size()){
+		min_points = input_data.size();
+	}
+	if(min_points > d_fft_bin_size){
+		min_points = d_fft_bin_size;
+	}
+	for(unsigned int point = 0; point < min_points; point++){
+		d_fft_data->operator[](point) = input_data[point];
+	}
+}
+
+void fft_display::update_display(){
+
+	// Tell the event loop to display the new data - the event loop handles deleting this object
+	qApp->postEvent(this, new fft_display_event(d_fft_data, d_start_frequency, d_stop_frequency));
+
+}
+
+void fft_display::customEvent(QCustomEvent* e){
+	if(e->type() == fft_display_event::EVENT_TYPE_ID){
+		fft_display_event* fft_display_event_ptr = (fft_display_event*)e;
+		// Write out the FFT data to the display here
+
+		gr_complex data_value;
+		for(unsigned int number = 0; number < fft_display_event_ptr->get_fft_data().size(); number++){
+			data_value = fft_display_event_ptr->get_fft_data()[number];
+			d_plot_data[number] = abs(data_value);
+#warning Add code here for handling magnitude, scaling, etc...
+
+			d_x_data[number] = d_start_frequency + ((d_stop_frequency-d_start_frequency) / static_cast<float>(d_fft_bin_size)*static_cast<float>(number));
+		}
+
+    		// Axis 
+    		setAxisTitle(QwtPlot::xBottom, "Frequency (Hz)");
+    		setAxisScale(QwtPlot::xBottom, fft_display_event_ptr->get_start_frequency(), fft_display_event_ptr->get_stop_frequency());
+
+    		setAxisTitle(QwtPlot::yLeft, "Values");
+		replot();
+	}
+}
+
+void fft_display::set_start_frequency(const float new_freq){
+	d_start_frequency = new_freq;
+}
+
+float fft_display::get_start_frequency()const{
+	return d_start_frequency;
+}
+
+void fft_display::set_stop_frequency(const float new_freq){
+	d_stop_frequency = new_freq;
+}
+
+float fft_display::get_stop_frequency()const{
+	return d_stop_frequency;
+}
+
+unsigned int fft_display::get_fft_bin_size()const{
+	return d_fft_bin_size;
+}
+
+
+#endif /* FFT_DISPLAY_CC */
diff --git a/gr-qtgui/src/lib/fftdisplay.h b/gr-qtgui/src/lib/fftdisplay.h
new file mode 100644
index 0000000000..c567e88f5b
--- /dev/null
+++ b/gr-qtgui/src/lib/fftdisplay.h
@@ -0,0 +1,61 @@
+#ifndef FFT_DISPLAY_H
+#define FFT_DISPLAY_H
+
+#include <gr_complex.h>
+
+#include <vector>
+
+#include <qwidget.h>
+#include <qwt_plot.h>
+#include <qevent.h>
+
+class fft_display_event:public QCustomEvent{
+public:
+	fft_display_event(std::vector<gr_complex>*, const float, const float);
+	~fft_display_event();
+
+	const std::vector<gr_complex>& get_fft_data()const;
+	float get_start_frequency()const;
+	float get_stop_frequency()const;
+
+	static const int EVENT_TYPE_ID;
+protected:
+
+private:
+	std::vector<gr_complex> d_fft_data;
+	float d_start_frequency;
+	float d_stop_frequency;
+};
+
+class fft_display:public QwtPlot{
+	Q_OBJECT
+public:	
+	fft_display(const unsigned int, QWidget* = ((QWidget*)0));
+	virtual ~fft_display();
+
+	virtual void customEvent(QCustomEvent*);
+
+	void set_start_frequency(const float);
+	float get_start_frequency()const;
+
+	void set_stop_frequency(const float);
+	float get_stop_frequency()const;
+
+	unsigned int get_fft_bin_size()const;
+
+public slots:
+	virtual void set_data( const std::vector<gr_complex>& );
+	virtual void update_display();
+
+protected:
+
+private:
+	std::vector<gr_complex>* d_fft_data;
+	double* d_plot_data;
+	double* d_x_data;
+	unsigned int d_fft_bin_size;
+	float d_start_frequency;
+	float d_stop_frequency;
+};
+
+#endif /* FFT_DISPLAY_H */
diff --git a/gr-qtgui/src/lib/fftdisplaysink.h b/gr-qtgui/src/lib/fftdisplaysink.h
new file mode 100644
index 0000000000..f6583f91d2
--- /dev/null
+++ b/gr-qtgui/src/lib/fftdisplaysink.h
@@ -0,0 +1,16 @@
+#ifndef FFT_DISPLAY_SINK_H
+#define FFT_DISPLAY_SINK_H
+
+
+class FFTDisplaySink{
+
+public:	
+	FFTDisplaySink();
+	~FFTDisplaySink();
+protected:
+
+private:
+
+};
+
+#endif /* FFT_DISPLAY_SINK_H */
diff --git a/gr-qtgui/src/lib/qt_examples.cc b/gr-qtgui/src/lib/qt_examples.cc
new file mode 100644
index 0000000000..d79a3ad6c5
--- /dev/null
+++ b/gr-qtgui/src/lib/qt_examples.cc
@@ -0,0 +1,122 @@
+#include <stdio.h>
+#include <unistd.h>
+
+#include <iostream>
+#include <fstream>
+
+#include <qapplication.h>
+#include <omnithread.h>
+#include <vector>
+
+#include <fftdisplay.h>
+
+#warning Must make this threadsafe
+static bool g_exit_flag = false;
+
+void read_function(void* ptr){
+
+	fft_display* fftDisplay = (fft_display*)ptr;
+
+	std::vector<gr_complex> fftData(fftDisplay->get_fft_bin_size());
+	for(unsigned int number = 0; number < fftData.size(); number++){
+		fftData[number] = gr_complex(static_cast<float>(number), static_cast<float>(number));
+	}
+
+	float* readBuffer = new float[fftDisplay->get_fft_bin_size()*2];
+	int amntRead = 0;
+
+	fftDisplay->set_data(fftData);
+
+	while(!g_exit_flag){
+	        // Read in the data here
+		sched_yield();
+		std::cin.read((char*)readBuffer, fftDisplay->get_fft_bin_size()*sizeof(gr_complex));
+		amntRead = std::cin.gcount();
+
+		if(amntRead != static_cast<int>(fftDisplay->get_fft_bin_size()*sizeof(gr_complex))){
+			fprintf(stderr, "Invalid Read Amount from stdin - closing program\n");
+			qApp->quit();
+			g_exit_flag = true;
+		}
+		else{
+			for(unsigned int number = 0; number < fftData.size(); number++){
+				fftData[number] = gr_complex(readBuffer[2*number], readBuffer[(2*number)+1]);
+			}
+
+			fftDisplay->set_data(fftData);
+
+			fftDisplay->update_display();
+
+			qApp->wakeUpGuiThread();
+		}
+	}	
+
+	delete[] readBuffer;
+}
+
+int main (int argc, char* argv[]){
+	extern char* optarg;
+	extern int optind, optopt;
+	float start_frequency = 0.0;
+	float stop_frequency = 4000.0;
+	int c;
+	unsigned int fft_bin_size = 1024;
+
+	while ((c = getopt(argc, argv, "s:p:b:")) != -1){
+		switch(c){
+		case 's': start_frequency = strtod(optarg, NULL); break;
+		case 'p': stop_frequency = strtod(optarg, NULL); break;
+		case 'b': fft_bin_size = (unsigned int)(atoi(optarg)); break;
+		case ':': /* -s or -p w/o operand */
+		fprintf(stderr, "Option -%c requires an arguement\n", optopt); break;
+		case '?': fprintf(stderr, "Unrecognized option: -%c\n", optopt);
+			  fprintf(stderr, "Valid Arguements\n -s <start frequency>\n -p <stop frequency> -b <fft_bin_size> - number of fft samples per display\n");
+			  exit(-1); break;
+		}
+	}
+
+	// Verify the stop frequency is greater than the stop frequency
+	if(stop_frequency < start_frequency){
+		fprintf(stderr, "Stop Frequency (%0.0f Hz) was less than the Start Frequency (%0.0f Hz)\n", stop_frequency, start_frequency);
+		exit(-1);
+	}
+
+	// Create the QApplication - this MUST be done before ANY QObjects are created
+	QApplication* qApp = new QApplication(argc, argv);
+
+	fft_display* fftDisplay = new fft_display(fft_bin_size); // No Parent Specified
+
+	// Resize the Display
+	fftDisplay->resize(640,240);
+
+	// Set the start and stop frequency
+	fftDisplay->set_start_frequency(start_frequency);
+	fftDisplay->set_stop_frequency(stop_frequency);
+
+	g_exit_flag = false;
+	omni_thread* thread_ptr = new omni_thread(&read_function, (void*)fftDisplay);
+	
+	// Set up the thread to read the data from stdin
+	thread_ptr->start();
+	sched_yield();
+
+	// Make the closing of the last window call the quit()
+	QObject::connect(qApp, SIGNAL(lastWindowClosed()), qApp, SLOT(quit()));
+
+	// finally, refresh the plot
+	fftDisplay->update_display();
+	fftDisplay->show();
+
+	// Start the Event Thread
+	qApp->exec();
+
+	// No QObjects should be deleted once the event thread exits...
+	g_exit_flag = true;
+
+	delete fftDisplay;
+
+	// Destroy the Event Thread
+	delete qApp;
+	return 0;
+}
+
-- 
cgit v1.2.3