QGIS API Documentation  2.5.0-Master
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
qgsoptionsdialogbase.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsoptionsdialogbase.cpp - base vertical tabs option dialog
3 
4  ---------------------
5  begin : March 24, 2013
6  copyright : (C) 2013 by Larry Shaffer
7  email : larrys at dakcarto dot com
8  ***************************************************************************
9  * *
10  * This program is free software; you can redistribute it and/or modify *
11  * it under the terms of the GNU General Public License as published by *
12  * the Free Software Foundation; either version 2 of the License, or *
13  * (at your option) any later version. *
14  * *
15  ***************************************************************************/
16 
17 #include "qgsoptionsdialogbase.h"
18 
19 #include <QDialog>
20 #include <QDialogButtonBox>
21 #include <QLayout>
22 #include <QListWidget>
23 #include <QMessageBox>
24 #include <QScrollBar>
25 #include <QStackedWidget>
26 #include <QSplitter>
27 #include <QTimer>
28 
29 
30 QgsOptionsDialogBase::QgsOptionsDialogBase( QString settingsKey, QWidget* parent, Qt::WindowFlags fl, QSettings* settings )
31  : QDialog( parent, fl )
32  , mOptsKey( settingsKey )
33  , mInit( false )
34  , mDialogTitle( "" )
35  , mSettings( settings )
36 {
37 }
38 
40 {
41  if ( mInit )
42  {
43  mSettings->setValue( QString( "/Windows/%1/geometry" ).arg( mOptsKey ), saveGeometry() );
44  mSettings->setValue( QString( "/Windows/%1/splitState" ).arg( mOptsKey ), mOptSplitter->saveState() );
45  mSettings->setValue( QString( "/Windows/%1/tab" ).arg( mOptsKey ), mOptStackedWidget->currentIndex() );
46  }
47 
48  if ( mDelSettings ) // local settings obj to delete
49  {
50  delete mSettings;
51  }
52 
53  mSettings = 0; // null the pointer (in case of outside settings obj)
54 }
55 
56 void QgsOptionsDialogBase::initOptionsBase( bool restoreUi, QString title )
57 {
58  // use pointer to app QSettings if no custom QSettings specified
59  // custom QSettings object may be from Python plugin
60  mDelSettings = false;
61 
62  if ( !mSettings )
63  {
64  mSettings = new QSettings();
65  mDelSettings = true; // only delete obj created by class
66  }
67 
68  // save dialog title so it can be used to be concatenated
69  // with category title in icon-only mode
70  if ( title.isEmpty() )
71  mDialogTitle = windowTitle();
72  else
73  mDialogTitle = title;
74 
75  // don't add to dialog margins
76  // redefine now, or those in inherited .ui file will be added
77  if ( layout() )
78  {
79  layout()->setContentsMargins( 0, 0, 0, 0 ); // Qt default spacing
80  }
81 
82  // start with copy of qgsoptionsdialog_template.ui to ensure existence of these objects
83  mOptListWidget = findChild<QListWidget*>( "mOptionsListWidget" );
84  QFrame* optionsFrame = findChild<QFrame*>( "mOptionsFrame" );
85  mOptStackedWidget = findChild<QStackedWidget*>( "mOptionsStackedWidget" );
86  mOptSplitter = findChild<QSplitter*>( "mOptionsSplitter" );
87  mOptButtonBox = findChild<QDialogButtonBox*>( "buttonBox" );
88  QFrame* buttonBoxFrame = findChild<QFrame*>( "mButtonBoxFrame" );
89 
90  if ( !mOptListWidget || !mOptStackedWidget || !mOptSplitter || !optionsFrame )
91  {
92  return;
93  }
94 
95  int size = mSettings->value( "/IconSize", 24 ).toInt();
96  // buffer size to match displayed icon size in toolbars, and expected geometry restore
97  // newWidth (above) may need adjusted if you adjust iconBuffer here
98  int iconBuffer = 4;
99  mOptListWidget->setIconSize( QSize( size + iconBuffer, size + iconBuffer ) );
100  mOptListWidget->setFrameStyle( QFrame::NoFrame );
101 
102  optionsFrame->layout()->setContentsMargins( 0, 3, 3, 3 );
103  QVBoxLayout* layout = static_cast<QVBoxLayout*>( optionsFrame->layout() );
104 
105  if ( buttonBoxFrame )
106  {
107  buttonBoxFrame->layout()->setContentsMargins( 0, 0, 0, 0 );
108  layout->insertWidget( layout->count() + 1, buttonBoxFrame );
109  }
110  else
111  {
112  layout->insertWidget( layout->count() + 1, mOptButtonBox );
113  }
114 
115  if ( mOptButtonBox )
116  {
117  // enforce only one connection per signal, in case added in Qt Designer
118  disconnect( mOptButtonBox, SIGNAL( accepted() ), this, SLOT( accept() ) );
119  connect( mOptButtonBox, SIGNAL( accepted() ), this, SLOT( accept() ) );
120  disconnect( mOptButtonBox, SIGNAL( rejected() ), this, SLOT( reject() ) );
121  connect( mOptButtonBox, SIGNAL( rejected() ), this, SLOT( reject() ) );
122  }
123  connect( mOptSplitter, SIGNAL( splitterMoved( int, int ) ), this, SLOT( updateOptionsListVerticalTabs() ) );
124  connect( mOptStackedWidget, SIGNAL( currentChanged( int ) ), this, SLOT( optionsStackedWidget_CurrentChanged( int ) ) );
125  connect( mOptStackedWidget, SIGNAL( widgetRemoved( int ) ), this, SLOT( optionsStackedWidget_WidgetRemoved( int ) ) );
126 
127  mInit = true;
128 
129  if ( restoreUi )
131 }
132 
133 void QgsOptionsDialogBase::setSettings( QSettings* settings )
134 {
135  if ( mDelSettings ) // local settings obj to delete
136  {
137  delete mSettings;
138  }
139 
140  mSettings = settings;
141  mDelSettings = false; // don't delete outside obj
142 }
143 
145 {
146  if ( !mInit )
147  {
148  return;
149  }
150 
151  if ( !title.isEmpty() )
152  {
153  mDialogTitle = title;
155  }
156 
157  // re-save original dialog title in case it was changed after dialog initialization
158  mDialogTitle = windowTitle();
159 
160  restoreGeometry( mSettings->value( QString( "/Windows/%1/geometry" ).arg( mOptsKey ) ).toByteArray() );
161  // mOptListWidget width is fixed to take up less space in QtDesigner
162  // revert it now unless the splitter's state hasn't been saved yet
163  mOptListWidget->setMaximumWidth(
164  mSettings->value( QString( "/Windows/%1/splitState" ).arg( mOptsKey ) ).isNull() ? 150 : 16777215 );
165  mOptSplitter->restoreState( mSettings->value( QString( "/Windows/%1/splitState" ).arg( mOptsKey ) ).toByteArray() );
166  int curIndx = mSettings->value( QString( "/Windows/%1/tab" ).arg( mOptsKey ), 0 ).toInt();
167 
168  // if the last used tab is out of range or not enabled display the first enabled one
169  if ( mOptStackedWidget->count() < ( curIndx + 1 )
170  || !mOptStackedWidget->widget( curIndx )->isEnabled() )
171  {
172  curIndx = 0;
173  for ( int i = 0; i < mOptStackedWidget->count(); i++ )
174  {
175  if ( mOptStackedWidget->widget( i )->isEnabled() )
176  {
177  curIndx = i;
178  break;
179  }
180  }
181  }
182 
183  if ( mOptStackedWidget->count() != 0 && mOptListWidget->count() != 0 )
184  {
185  mOptStackedWidget->setCurrentIndex( curIndx );
186  mOptListWidget->setCurrentRow( curIndx );
187  }
188 
189  // get rid of annoying outer focus rect on Mac
190  mOptListWidget->setAttribute( Qt::WA_MacShowFocusRect, false );
191 }
192 
193 void QgsOptionsDialogBase::showEvent( QShowEvent* e )
194 {
195  if ( mInit )
196  {
199  }
200  else
201  {
202  QTimer::singleShot( 0, this, SLOT( warnAboutMissingObjects() ) );
203  }
204 
205  QDialog::showEvent( e );
206 }
207 
208 void QgsOptionsDialogBase::paintEvent( QPaintEvent* e )
209 {
210  if ( mInit )
211  QTimer::singleShot( 0, this, SLOT( updateOptionsListVerticalTabs() ) );
212 
213  QDialog::paintEvent( e );
214 }
215 
217 {
218  QListWidgetItem *curitem = mOptListWidget->currentItem();
219  if ( curitem )
220  {
221  setWindowTitle( QString( "%1 | %2" ).arg( mDialogTitle ).arg( curitem->text() ) );
222  }
223  else
224  {
225  setWindowTitle( mDialogTitle );
226  }
227 }
228 
230 {
231  if ( !mInit )
232  return;
233 
234  if ( mOptListWidget->maximumWidth() != 16777215 )
235  mOptListWidget->setMaximumWidth( 16777215 );
236  // auto-resize splitter for vert scrollbar without covering icons in icon-only mode
237  // TODO: mOptListWidget has fixed 32px wide icons for now, allow user-defined
238  // Note: called on splitter resize and dialog paint event, so only update when necessary
239  int iconWidth = mOptListWidget->iconSize().width();
240  int snapToIconWidth = iconWidth + 32;
241 
242  QList<int> splitSizes = mOptSplitter->sizes();
243  mIconOnly = ( splitSizes.at( 0 ) <= snapToIconWidth );
244 
245  // iconBuffer (above) may need adjusted if you adjust iconWidth here
246  int newWidth = mOptListWidget->verticalScrollBar()->isVisible() ? iconWidth + 22 : iconWidth + 9;
247  bool diffWidth = mOptListWidget->minimumWidth() != newWidth;
248 
249  if ( diffWidth )
250  mOptListWidget->setMinimumWidth( newWidth );
251 
252  if ( mIconOnly && ( diffWidth || mOptListWidget->width() != newWidth ) )
253  {
254  splitSizes[1] = splitSizes.at( 1 ) - ( splitSizes.at( 0 ) - newWidth );
255  splitSizes[0] = newWidth;
256  mOptSplitter->setSizes( splitSizes );
257  }
258 
259  if ( mOptListWidget->wordWrap() && mIconOnly )
260  mOptListWidget->setWordWrap( false );
261  if ( !mOptListWidget->wordWrap() && !mIconOnly )
262  mOptListWidget->setWordWrap( true );
263 }
264 
266 {
267  mOptListWidget->blockSignals( true );
268  mOptListWidget->setCurrentRow( indx );
269  mOptListWidget->blockSignals( false );
270 
272 }
273 
275 {
276  // will need to take item first, if widgets are set for item in future
277  delete mOptListWidget->item( indx );
278 }
279 
281 {
282  QMessageBox::warning( 0, tr( "Missing objects" ),
283  tr( "Base options dialog could not be initialized.\n\n"
284  "Missing some of the .ui template objects:\n" )
285  + " mOptionsListWidget,\n mOptionsStackedWidget,\n mOptionsSplitter",
286  QMessageBox::Ok,
287  QMessageBox::Ok );
288 }
void setSettings(QSettings *settings)
void restoreOptionsBaseUi(QString title=QString())
Restore the base ui.
void paintEvent(QPaintEvent *e)
void optionsStackedWidget_WidgetRemoved(int indx)
QgsOptionsDialogBase(QString settingsKey, QWidget *parent=0, Qt::WindowFlags fl=0, QSettings *settings=0)
Constructor.
void showEvent(QShowEvent *e)
QDialogButtonBox * mOptButtonBox
void initOptionsBase(bool restoreUi=true, QString title=QString())
Set up the base ui connections for vertical tabs.
void optionsStackedWidget_CurrentChanged(int indx)
QStackedWidget * mOptStackedWidget
double size
Definition: qgssvgcache.cpp:77
QPointer< QSettings > mSettings
#define tr(sourceText)