diff options
author | Timothy Pearson <kb9vqf@pearsoncomputing.net> | 2011-11-08 12:31:36 -0600 |
---|---|---|
committer | Timothy Pearson <kb9vqf@pearsoncomputing.net> | 2011-11-08 12:31:36 -0600 |
commit | d796c9dd933ab96ec83b9a634feedd5d32e1ba3f (patch) | |
tree | 6e3dcca4f77e20ec8966c666aac7c35bd4704053 /doc/html/tutorial2-05.html | |
download | tqt3-d796c9dd933ab96ec83b9a634feedd5d32e1ba3f.tar.gz tqt3-d796c9dd933ab96ec83b9a634feedd5d32e1ba3f.zip |
Test conversion to TQt3 from Qt3 8c6fc1f8e35fd264dd01c582ca5e7549b32ab731
Diffstat (limited to 'doc/html/tutorial2-05.html')
-rw-r--r-- | doc/html/tutorial2-05.html | 587 |
1 files changed, 587 insertions, 0 deletions
diff --git a/doc/html/tutorial2-05.html b/doc/html/tutorial2-05.html new file mode 100644 index 000000000..9f9bbec06 --- /dev/null +++ b/doc/html/tutorial2-05.html @@ -0,0 +1,587 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> +<!-- /home/espenr/tmp/qt-3.3.8-espenr-2499/qt-x11-free-3.3.8/doc/tutorial2.doc:349 --> +<html> +<head> +<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> +<title>Presenting the GUI</title> +<style type="text/css"><!-- +fn { margin-left: 1cm; text-indent: -1cm; } +a:link { color: #004faf; text-decoration: none } +a:visited { color: #672967; text-decoration: none } +body { background: #ffffff; color: black; } +--></style> +</head> +<body> + +<table border="0" cellpadding="0" cellspacing="0" width="100%"> +<tr bgcolor="#E5E5E5"> +<td valign=center> + <a href="index.html"> +<font color="#004faf">Home</font></a> + | <a href="classes.html"> +<font color="#004faf">All Classes</font></a> + | <a href="mainclasses.html"> +<font color="#004faf">Main Classes</font></a> + | <a href="annotated.html"> +<font color="#004faf">Annotated</font></a> + | <a href="groups.html"> +<font color="#004faf">Grouped Classes</font></a> + | <a href="functions.html"> +<font color="#004faf">Functions</font></a> +</td> +<td align="right" valign="center"><img src="logo32.png" align="right" width="64" height="32" border="0"></td></tr></table><h1 align=center>Presenting the GUI</h1> + + +<p> +<p> <center><img src="chart-main2.png" alt="The chart application"></center> +<p> The <tt>chart</tt> application provides access to options via menus and +toolbar buttons arranged around a central widget, a CanvasView, in a +conventional document-centric style. +<p> (Extracts from <tt>chartform.h</tt>.) +<p> + +<pre> class ChartForm: public <a href="qmainwindow.html">TQMainWindow</a> + { + <a href="metaobjects.html#Q_OBJECT">Q_OBJECT</a> + public: + enum { MAX_ELEMENTS = 100 }; + enum { MAX_RECENTFILES = 9 }; // Must not exceed 9 + enum ChartType { PIE, VERTICAL_BAR, HORIZONTAL_BAR }; + enum AddValuesType { NO, YES, AS_PERCENTAGE }; + + ChartForm( const <a href="qstring.html">TQString</a>& filename ); + ~ChartForm(); + + int chartType() { return m_chartType; } + void setChanged( bool changed = TRUE ) { m_changed = changed; } + void drawElements(); + + <a href="qpopupmenu.html">TQPopupMenu</a> *optionsMenu; // Why public? See canvasview.cpp + + protected: + virtual void closeEvent( <a href="qcloseevent.html">TQCloseEvent</a> * ); + + private slots: + void fileNew(); + void fileOpen(); + void fileOpenRecent( int index ); + void fileSave(); + void fileSaveAs(); + void fileSaveAsPixmap(); + void filePrint(); + void fileQuit(); + void optionsSetData(); + void updateChartType( <a href="qaction.html">TQAction</a> *action ); + void optionsSetFont(); + void optionsSetOptions(); + void helpHelp(); + void helpAbout(); + void helpAboutTQt(); + void saveOptions(); + + private: + void init(); + void load( const <a href="qstring.html">TQString</a>& filename ); + bool okToClear(); + void drawPieChart( const double scales[], double total, int count ); + void drawVerticalBarChart( const double scales[], double total, int count ); + void drawHorizontalBarChart( const double scales[], double total, int count ); + + <a href="qstring.html">TQString</a> valueLabel( const <a href="qstring.html">TQString</a>& label, double value, double total ); + void updateRecentFiles( const <a href="qstring.html">TQString</a>& filename ); + void updateRecentFilesMenu(); + void setChartType( ChartType chartType ); + + <a href="qpopupmenu.html">TQPopupMenu</a> *fileMenu; + <a href="qaction.html">TQAction</a> *optionsPieChartAction; + <a href="qaction.html">TQAction</a> *optionsHorizontalBarChartAction; + <a href="qaction.html">TQAction</a> *optionsVerticalBarChartAction; + <a href="qstring.html">TQString</a> m_filename; + <a href="qstringlist.html">TQStringList</a> m_recentFiles; + <a href="qcanvas.html">TQCanvas</a> *m_canvas; + CanvasView *m_canvasView; + bool m_changed; + ElementVector m_elements; + <a href="qprinter.html">TQPrinter</a> *m_printer; + ChartType m_chartType; + AddValuesType m_addValues; + int m_decimalPlaces; + <a href="qfont.html">TQFont</a> m_font; + }; +</pre> +<p> We create a <tt>ChartForm</tt> subclass of <a href="qmainwindow.html">TQMainWindow</a>. Our subclass uses +the <a href="metaobjects.html#Q_OBJECT">Q_OBJECT</a> macro to support TQt's <a href="signalsandslots.html">signals and slots</a> mechanism. +<p> The public interface is very small; the type of chart being displayed +can be retrieved, the chart can be marked 'changed' (so that the user +will be prompted to save on exit), and the chart can be asked to draw +itself (drawElements()). We've also made the options menu public +because we are also going to use this menu as the canvas view's +context menu. +<p> <center><table cellpadding="4" cellspacing="2" border="0"> +<tr bgcolor="#f0f0f0"> +<td valign="top">The <a href="qcanvas.html">TQCanvas</a> class is used for drawing 2D vector graphics. The +<a href="qcanvasview.html">TQCanvasView</a> class is used to present a view of a canvas in an +application's GUI. All our drawing operations take place on the +canvas; but events (e.g. mouse clicks) take place on the canvas view. +</table></center> +<p> Each action is represented by a private slot, e.g. <tt>fileNew()</tt>, <tt>optionsSetData()</tt>, etc. We also have tquite a number of private +functions and data members; we'll look at all these as we go through +the implementation. +<p> For the sake of convenience and compilation speed the chart form's +implementation is split over three files, <tt>chartform.cpp</tt> for the +GUI, <tt>chartform_canvas.cpp</tt> for the canvas handling and <tt>chartform_files.cpp</tt> for the file handling. We'll review each in turn. +<p> <h2> The Chart Form GUI +</h2> +<a name="1"></a><p> (Extracts from <tt>chartform.cpp</tt>.) +<p> + +<pre> #include "images/file_new.xpm" + #include "images/file_open.xpm" +</pre><pre> #include "images/options_piechart.xpm" +</pre> +<p> All the images used by <tt>chart</tt> have been created as <tt>.xpm</tt> files +which we've placed in the <tt>images</tt> subdirectory. +<p> <h2> The Constructor +</h2> +<a name="2"></a><p> <pre> ChartForm::ChartForm( const <a href="qstring.html">TQString</a>& filename ) + : <a href="qmainwindow.html">TQMainWindow</a>( 0, 0, WDestructiveClose ) +</pre><tt>...</tt> +<pre> <a href="qaction.html">TQAction</a> *fileNewAction; + <a href="qaction.html">TQAction</a> *fileOpenAction; + <a href="qaction.html">TQAction</a> *fileSaveAction; +</pre> +<p> For each user action we declare a <a href="qaction.html">TQAction</a> pointer. Some actions are +declared in the header file because they need to be referred to +outside of the constructor. +<p> <center><table cellpadding="4" cellspacing="2" border="0"> +<tr bgcolor="#d0d0d0"> +<td valign="top">Most user actions are suitable as both menu items and as toolbar +buttons. TQt allows us to create a single TQAction which can be added to +both a menu and a toolbar. This approach ensures that menu items and +toolbar buttons stay in sync and saves duplicating code. +</table></center> +<p> <pre> fileNewAction = new <a href="qaction.html">TQAction</a>( + "New Chart", TQPixmap( file_new ), + "&New", CTRL+Key_N, this, "new" ); + <a href="qobject.html#connect">connect</a>( fileNewAction, SIGNAL( <a href="qaction.html#activated">activated</a>() ), this, SLOT( fileNew() ) ); +</pre> +<p> When we construct an action we give it a name, an optional icon, a +menu text, and an accelerator short-cut key (or 0 if no accelerator is +retquired). We also make it a child of the form (by passing <tt>this</tt>). +When the user clicks a toolbar button or clicks a menu option the <tt>activated()</tt> signal is emitted. We connect() this signal to the +action's slot, in the snippet shown above, to fileNew(). +<p> The chart types are all mutually exclusive: you can have a pie chart +<em>or</em> a vertical bar chart <em>or</em> a horizontal bar chart. This means +that if the user selects the pie chart menu option, the pie chart +toolbar button must be automatically selected too, and the other chart +menu options and toolbar buttons must be automatically unselected. +This behaviour is achieved by creating a <a href="qactiongroup.html">TQActionGroup</a> and placing the +chart type actions in the group. +<p> <pre> <a href="qactiongroup.html">TQActionGroup</a> *chartGroup = new <a href="qactiongroup.html">TQActionGroup</a>( this ); // Connected later + chartGroup-><a href="qactiongroup.html#setExclusive">setExclusive</a>( TRUE ); +</pre> +<p> The action group becomes a child of the form (<tt>this</tt>) and the +exlusive behaviour is achieved by the setExclusive() call. +<p> <pre> optionsPieChartAction = new <a href="qaction.html">TQAction</a>( + "Pie Chart", TQPixmap( options_piechart ), + "&Pie Chart", CTRL+Key_I, chartGroup, "pie chart" ); + optionsPieChartAction-><a href="qaction.html#setToggleAction">setToggleAction</a>( TRUE ); +</pre> +<p> Each action in the group is created in the same way as other actions, +except that the action's parent is the group rather than the form. +Because our chart type actions have an on/off state we call +setToggleAction(TRUE) for each of them. Note that we do not connect +the actions; instead, later on, we will connect the group to a slot +that will cause the canvas to redraw. +<p> <center><table cellpadding="4" cellspacing="2" border="0"> +<tr bgcolor="#f0f0f0"> +<td valign="top">Why haven't we connected the group straight away? Later in the +constructor we will read the user's options, one of which is the chart +type. We will then set the chart type accordingly. But at that point +we still won't have created a canvas or have any data, so all we want +to do is toggle the canvas type toolbar buttons, but not actually draw +the (at this point non-existent) canvas. <em>After</em> we have set the +canvas type we will connect the group. +</table></center> +<p> Once we've created all our user actions we can create the toolbars and +menu options that will allow the user to invoke them. +<p> <pre> <a href="qtoolbar.html">TQToolBar</a>* fileTools = new <a href="qtoolbar.html">TQToolBar</a>( this, "file operations" ); + fileTools-><a href="qtoolbar.html#setLabel">setLabel</a>( "File Operations" ); + fileNewAction-><a href="qaction.html#addTo">addTo</a>( fileTools ); + fileOpenAction-><a href="qaction.html#addTo">addTo</a>( fileTools ); + fileSaveAction-><a href="qaction.html#addTo">addTo</a>( fileTools ); +</pre><tt>...</tt> +<pre> fileMenu = new <a href="qpopupmenu.html">TQPopupMenu</a>( this ); + <a href="qmainwindow.html#menuBar">menuBar</a>()->insertItem( "&File", fileMenu ); + fileNewAction-><a href="qaction.html#addTo">addTo</a>( fileMenu ); + fileOpenAction-><a href="qaction.html#addTo">addTo</a>( fileMenu ); + fileSaveAction-><a href="qaction.html#addTo">addTo</a>( fileMenu ); +</pre> +<p> Toolbar actions and menu options are easily created from TQActions. +<p> As a convenience to our users we will restore the last window position +and size and list their recently used files. This is achieved by +writing out their settings when the application is closed and reading +them back when we construct the form. +<p> <pre> <a href="qsettings.html">TQSettings</a> settings; + settings.<a href="qsettings.html#insertSearchPath">insertSearchPath</a>( TQSettings::Windows, WINDOWS_REGISTRY ); + int windowWidth = settings.<a href="qsettings.html#readNumEntry">readNumEntry</a>( APP_KEY + "WindowWidth", 460 ); + int windowHeight = settings.<a href="qsettings.html#readNumEntry">readNumEntry</a>( APP_KEY + "WindowHeight", 530 ); + int windowX = settings.<a href="qsettings.html#readNumEntry">readNumEntry</a>( APP_KEY + "WindowX", -1 ); + int windowY = settings.<a href="qsettings.html#readNumEntry">readNumEntry</a>( APP_KEY + "WindowY", -1 ); + setChartType( ChartType( + settings.<a href="qsettings.html#readNumEntry">readNumEntry</a>( APP_KEY + "ChartType", int(PIE) ) ) ); +</pre><pre> m_font = TQFont( "Helvetica", 18, TQFont::Bold ); + m_font.fromString( + settings.<a href="qsettings.html#readEntry">readEntry</a>( APP_KEY + "Font", m_font.toString() ) ); + for ( int i = 0; i < MAX_RECENTFILES; ++i ) { + <a href="qstring.html">TQString</a> filename = settings.<a href="qsettings.html#readEntry">readEntry</a>( APP_KEY + "File" + + TQString::<a href="qstring.html#number">number</a>( i + 1 ) ); + if ( !filename.<a href="qstring.html#isEmpty">isEmpty</a>() ) + m_recentFiles.push_back( filename ); + } + if ( m_recentFiles.count() ) + updateRecentFilesMenu(); +</pre> +<p> The <a href="qsettings.html">TQSettings</a> class handles user settings in a platform-independent +way. We simply read and write settings, leaving TQSettings to handle +the platform dependencies. The insertSearchPath() call does nothing +except under Windows so does not have to be <tt>#ifdef</tt>ed. +<p> We use readNumEntry() calls to obtain the chart form's last size and +position, providing default values if this is the first time it has +been run. The chart type is retrieved as an integer and cast to a +ChartType enum value. We create a default label font and then read the +"Font" setting, using the default we have just created if necessary. +<p> Although TQSettings can handle string lists we've chosen to store each +recently used file as a separate entry to make it easier to hand edit +the settings. We attempt to read each possible file entry ("File1" to +"File9"), and add each non-empty entry to the list of recently used +files. If there are one or more recently used files we update the File +menu by calling updateRecentFilesMenu(); (we'll review this later on). +<p> <pre> <a href="qobject.html#connect">connect</a>( chartGroup, SIGNAL( <a href="qactiongroup.html#selected">selected</a>(TQAction*) ), + this, SLOT( updateChartType(TQAction*) ) ); +</pre> +<p> Now that we have set the chart type (when we read it in as a user +setting) it is safe to connect the chart group to our +updateChartType() slot. +<p> <pre> <a href="qwidget.html#resize">resize</a>( windowWidth, windowHeight ); + if ( windowX != -1 || windowY != -1 ) + <a href="qwidget.html#move">move</a>( windowX, windowY ); +</pre> +<p> And now that we know the window size and position we can resize and +move the chart form's window accordingly. +<p> <pre> m_canvas = new <a href="qcanvas.html">TQCanvas</a>( this ); + m_canvas-><a href="qcanvas.html#resize">resize</a>( <a href="qwidget.html#width">width</a>(), height() ); + m_canvasView = new CanvasView( m_canvas, &m_elements, this ); + <a href="qmainwindow.html#setCentralWidget">setCentralWidget</a>( m_canvasView ); + m_canvasView-><a href="qwidget.html#show">show</a>(); +</pre> +<p> We create a new <a href="qcanvas.html">TQCanvas</a> and set its size to that of the chart form +window's client area. We also create a <tt>CanvasView</tt> (our own subclass +of <a href="qcanvasview.html">TQCanvasView</a>) to display the TQCanvas. We make the canvas view the +chart form's main widget and show it. +<p> <pre> if ( !filename.<a href="qstring.html#isEmpty">isEmpty</a>() ) + load( filename ); + else { + init(); + m_elements[0].set( 20, red, 14, "Red" ); + m_elements[1].set( 70, cyan, 2, "Cyan", darkGreen ); + m_elements[2].set( 35, blue, 11, "Blue" ); + m_elements[3].set( 55, yellow, 1, "Yellow", darkBlue ); + m_elements[4].set( 80, magenta, 1, "Magenta" ); + drawElements(); + } +</pre> +<p> If we have a file to load we load it; otherwise we initialise our +elements vector and draw a sample chart. +<p> <pre> <a href="qmainwindow.html#statusBar">statusBar</a>()->message( "Ready", 2000 ); +</pre> +<p> It is <em>vital</em> that we call statusBar() in the constructor, since the +call ensures that a status bar is created for this main window. +<p> <h3> init() +</h3> +<a name="2-1"></a><p> <pre> void ChartForm::init() + { + <a href="qwidget.html#setCaption">setCaption</a>( "Chart" ); + m_filename = <a href="qstring.html#TQString-null">TQString::null</a>; + m_changed = FALSE; + + m_elements[0] = Element( Element::INVALID, red ); + m_elements[1] = Element( Element::INVALID, cyan ); + m_elements[2] = Element( Element::INVALID, blue ); +</pre><tt>...</tt> +<p> We use an init() function because we want to initialise the canvas and +the elements (in the <tt>m_elements</tt> <tt>ElementVector</tt>) when the form is +constructed, and also whenever the user loads an existing data set or +creates a new data set. +<p> We reset the caption and set the current filename to TQString::null. We +also populate the elements vector with invalid elements. This isn't +necessary, but giving each element a different color is more +convenient for the user since when they enter values each one will +already have a unique color (which they can change of course). +<p> <h2> The File Handling Actions +</h2> +<a name="3"></a><p> <h3> okToClear() +</h3> +<a name="3-1"></a><p> <pre> bool ChartForm::okToClear() + { + if ( m_changed ) { + <a href="qstring.html">TQString</a> msg; + if ( m_filename.isEmpty() ) + msg = "Unnamed chart "; + else + msg = TQString( "Chart '%1'\n" ).arg( m_filename ); + msg += "has been changed."; + + int x = TQMessageBox::<a href="qmessagebox.html#information">information</a>( this, "Chart -- Unsaved Changes", + msg, "&Save", "Cancel", "&Abandon", + 0, 1 ); + switch( x ) { + case 0: // Save + fileSave(); + break; + case 1: // Cancel + default: + return FALSE; + case 2: // Abandon + break; + } + } + + return TRUE; + } +</pre> +<p> The okToClear() function is used to prompt the user to save their +values if they have any unsaved data. It is used by several other +functions. +<p> <h3> fileNew() +</h3> +<a name="3-2"></a><p> + +<pre> void ChartForm::fileNew() + { + if ( okToClear() ) { + init(); + drawElements(); + } + } +</pre> +<p> When the user invokes the fileNew() action we call okToClear() to give +them the opportunity to save any unsaved data. If they either save or +abandon or have no unsaved data we re-initialise the elements vector +and draw the default chart. +<p> <center><table cellpadding="4" cellspacing="2" border="0"> +<tr bgcolor="#d0d0d0"> +<td valign="top">Should we also have invoked optionsSetData() to pop up the dialog +through which the user can create and edit values, colors etc? You +could try running the application as it is, and then try it having +added a call to optionsSetData() and see which you prefer. +</table></center> +<p> <h3> fileOpen() +</h3> +<a name="3-3"></a><p> <pre> void ChartForm::fileOpen() + { + if ( !okToClear() ) + return; + + <a href="qstring.html">TQString</a> filename = TQFileDialog::<a href="qfiledialog.html#getOpenFileName">getOpenFileName</a>( + TQString::null, "Charts (*.cht)", this, + "file open", "Chart -- File Open" ); + <a name="x2567"></a> if ( !filename.<a href="qstring.html#isEmpty">isEmpty</a>() ) + load( filename ); + else + <a href="qmainwindow.html#statusBar">statusBar</a>()->message( "File Open abandoned", 2000 ); + } +</pre> +<p> We check that it is okToClear(). If it is we use the static +<a href="qfiledialog.html#getOpenFileName">TQFileDialog::getOpenFileName</a>() function to get the name of the file +the user wishes to load. If we get a filename we call load(). +<p> <h3> fileSaveAs() +</h3> +<a name="3-4"></a><p> <pre> void ChartForm::fileSaveAs() + { + <a href="qstring.html">TQString</a> filename = TQFileDialog::<a href="qfiledialog.html#getSaveFileName">getSaveFileName</a>( + TQString::null, "Charts (*.cht)", this, + "file save as", "Chart -- File Save As" ); + if ( !filename.<a href="qstring.html#isEmpty">isEmpty</a>() ) { + int answer = 0; + <a name="x2563"></a> if ( TQFile::<a href="qfile.html#exists">exists</a>( filename ) ) + <a name="x2566"></a> answer = TQMessageBox::<a href="qmessagebox.html#warning">warning</a>( + this, "Chart -- Overwrite File", + TQString( "Overwrite\n\'%1\'?" ). + arg( filename ), + "&Yes", "&No", TQString::null, 1, 1 ); + if ( answer == 0 ) { + m_filename = filename; + updateRecentFiles( filename ); + fileSave(); + return; + } + } + <a href="qmainwindow.html#statusBar">statusBar</a>()->message( "Saving abandoned", 2000 ); + } +</pre> +<p> This function calls the static <a href="qfiledialog.html#getSaveFileName">TQFileDialog::getSaveFileName</a>() to get +the name of the file to save the data in. If the file exists we use a +<a href="qmessagebox.html#warning">TQMessageBox::warning</a>() to notify the user and give them the option of +abandoning the save. If the file is to be saved we update the recently +opened files list and call fileSave() (covered in <a href="tutorial2-07.html">File Handling</a>) to perform the save. +<p> <h2> Managing a list of Recently Opened Files +</h2> +<a name="4"></a><p> + +<pre> <a href="qstringlist.html">TQStringList</a> m_recentFiles; +</pre> +<p> We hold the list of recently opened files in a string list. +<p> + +<pre> void ChartForm::updateRecentFilesMenu() + { + for ( int i = 0; i < MAX_RECENTFILES; ++i ) { + if ( fileMenu-><a href="qmenudata.html#findItem">findItem</a>( i ) ) + fileMenu-><a href="qmenudata.html#removeItem">removeItem</a>( i ); + if ( i < int(m_recentFiles.count()) ) + fileMenu-><a href="qmenudata.html#insertItem">insertItem</a>( TQString( "&%1 %2" ). + arg( i + 1 ).arg( m_recentFiles[i] ), + this, SLOT( fileOpenRecent(int) ), + 0, i ); + } + } +</pre> +<p> This function is called (usually via updateRecentFiles()) whenever the +user opens an existing file or saves a new file. For each file in the +string list we insert a new menu item. We prefix each filename with an +underlined number from <u>1</u> to <u>9</u> to support keyboard access +(e.g. <tt>Alt+F, 2</tt> to open the second file in the list). We give the +menu item an id which is the same as the index position of the item in +the string list, and connect each menu item to the fileOpenRecent() +slot. The old file menu items are deleted at the same time by going +through each possible recent file menu item id. This works because the +other file menu items had ids created by TQt (all of which are < 0); +whereas the menu items we're creating all have ids >= 0. +<p> + +<pre> void ChartForm::updateRecentFiles( const <a href="qstring.html">TQString</a>& filename ) + { + if ( m_recentFiles.find( filename ) != m_recentFiles.end() ) + return; + + m_recentFiles.push_back( filename ); + if ( m_recentFiles.count() > MAX_RECENTFILES ) + m_recentFiles.pop_front(); + + updateRecentFilesMenu(); + } +</pre> +<p> This is called when the user opens an existing file or saves a new +file. If the file is already in the list it simply returns. Otherwise +the file is added to the end of the list and if the list is too large +(> 9 files) the first (oldest) is removed. updateRecentFilesMenu() is +then called to recreate the list of recently used files in the File +menu. +<p> + +<pre> void ChartForm::fileOpenRecent( int index ) + { + if ( !okToClear() ) + return; + + load( m_recentFiles[index] ); + } +</pre> +<p> When the user selects a recently opened file the fileOpenRecent() slot +is called with the menu id of the file they have selected. Because we +made the file menu ids equal to the files' index positions in the +<tt>m_recentFiles</tt> list we can simply load the file indexed by the menu +item id. +<p> <h2> Quiting +</h2> +<a name="5"></a><p> <pre> void ChartForm::fileQuit() + { + if ( okToClear() ) { + saveOptions(); + qApp-><a href="qapplication.html#exit">exit</a>( 0 ); + } + } +</pre> +<p> When the user tquits we give them the opportunity to save any unsaved +data (okToClear()) then save their options, e.g. window size and +position, chart type, etc., before terminating. +<p> <pre> void ChartForm::saveOptions() + { + <a href="qsettings.html">TQSettings</a> settings; + settings.<a href="qsettings.html#insertSearchPath">insertSearchPath</a>( TQSettings::Windows, WINDOWS_REGISTRY ); + settings.<a href="qsettings.html#writeEntry">writeEntry</a>( APP_KEY + "WindowWidth", width() ); + settings.<a href="qsettings.html#writeEntry">writeEntry</a>( APP_KEY + "WindowHeight", height() ); + settings.<a href="qsettings.html#writeEntry">writeEntry</a>( APP_KEY + "WindowX", x() ); + settings.<a href="qsettings.html#writeEntry">writeEntry</a>( APP_KEY + "WindowY", y() ); + settings.<a href="qsettings.html#writeEntry">writeEntry</a>( APP_KEY + "ChartType", int(m_chartType) ); + settings.<a href="qsettings.html#writeEntry">writeEntry</a>( APP_KEY + "AddValues", int(m_addValues) ); + settings.<a href="qsettings.html#writeEntry">writeEntry</a>( APP_KEY + "Decimals", m_decimalPlaces ); + settings.<a href="qsettings.html#writeEntry">writeEntry</a>( APP_KEY + "Font", m_font.toString() ); + for ( int i = 0; i < int(m_recentFiles.count()); ++i ) + settings.<a href="qsettings.html#writeEntry">writeEntry</a>( APP_KEY + "File" + TQString::number( i + 1 ), + m_recentFiles[i] ); + } +</pre> +<p> Saving the user's options using <a href="qsettings.html">TQSettings</a> is straight-forward. +<p> <h2> Custom Dialogs +</h2> +<a name="6"></a><p> We want the user to be able to set some options manually and to create +and edit values, value colors, etc. +<p> + +<pre> void ChartForm::optionsSetOptions() + { + OptionsForm *optionsForm = new OptionsForm( this ); + optionsForm->chartTypeComboBox->setCurrentItem( m_chartType ); + optionsForm-><a href="qwidget.html#setFont">setFont</a>( m_font ); +</pre><pre> if ( optionsForm-><a href="qdialog.html#exec">exec</a>() ) { + setChartType( ChartType( + optionsForm->chartTypeComboBox->currentItem()) ); + m_font = optionsForm-><a href="qwidget.html#font">font</a>(); +</pre><pre> drawElements(); + } + delete optionsForm; + } +</pre> +<p> The form for setting options is provided by our custom <tt>OptionsForm</tt> +covered in <a href="tutorial2-09.html">Setting Options</a>. The +options form is a standard "dumb" dialog: we create an instance, set +all its GUI elements to the relevant settings, and if the user clicked +"OK" (exec() returns a true value) we read back settings from the GUI +elements. +<p> + +<pre> void ChartForm::optionsSetData() + { + SetDataForm *setDataForm = new SetDataForm( &m_elements, m_decimalPlaces, this ); + if ( setDataForm-><a href="qdialog.html#exec">exec</a>() ) { + m_changed = TRUE; + drawElements(); + } + delete setDataForm; + } +</pre> +<p> The form for creating and editing chart data is provided by our custom +<tt>SetDataForm</tt> covered in <a href="tutorial2-08.html">Taking Data</a>. +This form is a "smart" dialog. We pass in the data structure we want +to work on, and the dialog handles the presentation of the data +structure itself. If the user clicks "OK" the dialog will update the +data structure and exec() will return a true value. All we need to do +in optionsSetData() if the user changed the data is mark the chart as +changed and call drawElements() to redraw the chart with the new and +updated data. +<p> <p align="right"> +<a href="tutorial2-04.html">« Mainly Easy</a> | +<a href="tutorial2.html">Contents</a> | +<a href="tutorial2-06.html">Canvas Control »</a> +</p> +<p> +<!-- eof --> +<p><address><hr><div align=center> +<table width=100% cellspacing=0 border=0><tr> +<td>Copyright © 2007 +<a href="troll.html">Trolltech</a><td align=center><a href="trademarks.html">Trademarks</a> +<td align=right><div align=right>TQt 3.3.8</div> +</table></div></address></body> +</html> |