QGIS API Documentation  2.0.1-Dufour
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups 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 <QSettings>
26 #include <QStackedWidget>
27 #include <QSplitter>
28 #include <QTimer>
29 
30 
31 QgsOptionsDialogBase::QgsOptionsDialogBase( QString settingsKey, QWidget* parent, Qt::WFlags fl )
32  : QDialog( parent, fl ), mOptsKey( settingsKey ), mInit( false )
33 {
34 }
35 
37 {
38  if ( mInit )
39  {
40  QSettings settings;
41  settings.setValue( QString( "/Windows/%1/geometry" ).arg( mOptsKey ), saveGeometry() );
42  settings.setValue( QString( "/Windows/%1/splitState" ).arg( mOptsKey ), mOptSplitter->saveState() );
43  settings.setValue( QString( "/Windows/%1/tab" ).arg( mOptsKey ), mOptStackedWidget->currentIndex() );
44  }
45 }
46 
48 {
49  // don't add to dialog margins
50  // redefine now, or those in inherited .ui file will be added
51  if ( layout() )
52  layout()->setContentsMargins( 12, 12, 12, 12 ); // Qt default spacing
53 
54  // start with copy of qgsoptionsdialog_template.ui to ensure existence of these objects
55  mOptListWidget = findChild<QListWidget*>( "mOptionsListWidget" );
56  mOptStackedWidget = findChild<QStackedWidget*>( "mOptionsStackedWidget" );
57  mOptSplitter = findChild<QSplitter*>( "mOptionsSplitter" );
58  mOptButtonBox = findChild<QDialogButtonBox*>( "buttonBox" );
59 
60  if ( !mOptListWidget || !mOptStackedWidget || !mOptSplitter )
61  {
62  return;
63  }
64 
65  if ( mOptButtonBox )
66  {
67  // enforce only one connection per signal, in case added in Qt Designer
68  disconnect( mOptButtonBox, SIGNAL( accepted() ), this, SLOT( accept() ) );
69  connect( mOptButtonBox, SIGNAL( accepted() ), this, SLOT( accept() ) );
70  disconnect( mOptButtonBox, SIGNAL( rejected() ), this, SLOT( reject() ) );
71  connect( mOptButtonBox, SIGNAL( rejected() ), this, SLOT( reject() ) );
72  }
73  connect( mOptSplitter, SIGNAL( splitterMoved( int, int ) ), this, SLOT( updateOptionsListVerticalTabs() ) );
74  connect( mOptStackedWidget, SIGNAL( currentChanged( int ) ), this, SLOT( optionsStackedWidget_CurrentChanged( int ) ) );
75  connect( mOptStackedWidget, SIGNAL( widgetRemoved( int ) ), this, SLOT( optionsStackedWidget_WidgetRemoved( int ) ) );
76 
77  mInit = true;
78 
79  if ( restoreUi )
81 }
82 
84 {
85  if ( !mInit )
86  {
87  return;
88  }
89 
90  QSettings settings;
91  restoreGeometry( settings.value( QString( "/Windows/%1/geometry" ).arg( mOptsKey ) ).toByteArray() );
92  // mOptListWidget width is fixed to take up less space in QtDesigner
93  // revert it now unless the splitter's state hasn't been saved yet
94  mOptListWidget->setMaximumWidth(
95  settings.value( QString( "/Windows/%1/splitState" ).arg( mOptsKey ) ).isNull() ? 150 : 16777215 );
96  mOptSplitter->restoreState( settings.value( QString( "/Windows/%1/splitState" ).arg( mOptsKey ) ).toByteArray() );
97  int curIndx = settings.value( QString( "/Windows/%1/tab" ).arg( mOptsKey ), 0 ).toInt();
98 
99  // if the last used tab is out of range or not enabled display the first enabled one
100  if ( mOptStackedWidget->count() < ( curIndx + 1 )
101  || !mOptStackedWidget->widget( curIndx )->isEnabled() )
102  {
103  curIndx = 0;
104  for ( int i = 0; i < mOptStackedWidget->count(); i++ )
105  {
106  if ( mOptStackedWidget->widget( i )->isEnabled() )
107  {
108  curIndx = i;
109  break;
110  }
111  }
112  }
113 
114  if ( mOptStackedWidget->count() != 0 && mOptListWidget->count() != 0 )
115  {
116  mOptStackedWidget->setCurrentIndex( curIndx );
117  mOptListWidget->setCurrentRow( curIndx );
118  }
119 
120  // get rid of annoying outer focus rect on Mac
121  mOptListWidget->setAttribute( Qt::WA_MacShowFocusRect, false );
122 }
123 
124 void QgsOptionsDialogBase::showEvent( QShowEvent* e )
125 {
126  if ( mInit )
127  {
129  }
130  else
131  {
132  QTimer::singleShot( 0, this, SLOT( warnAboutMissingObjects() ) );
133  }
134 
135  QDialog::showEvent( e );
136 }
137 
138 void QgsOptionsDialogBase::paintEvent( QPaintEvent* e )
139 {
140  if ( mInit )
141  QTimer::singleShot( 0, this, SLOT( updateOptionsListVerticalTabs() ) );
142 
143  QDialog::paintEvent( e );
144 }
145 
147 {
148  if ( !mInit )
149  return;
150 
151  if ( mOptListWidget->maximumWidth() != 16777215 )
152  mOptListWidget->setMaximumWidth( 16777215 );
153  // auto-resize splitter for vert scrollbar without covering icons in icon-only mode
154  // TODO: mOptListWidget has fixed 32px wide icons for now, allow user-defined
155  // Note: called on splitter resize and dialog paint event, so only update when necessary
156  int iconWidth = mOptListWidget->iconSize().width();
157  int snapToIconWidth = iconWidth + 32;
158 
159  QList<int> splitSizes = mOptSplitter->sizes();
160  bool iconOnly = ( splitSizes.at( 0 ) <= snapToIconWidth );
161 
162  int newWidth = mOptListWidget->verticalScrollBar()->isVisible() ? iconWidth + 26 : iconWidth + 12;
163  bool diffWidth = mOptListWidget->minimumWidth() != newWidth;
164 
165  if ( diffWidth )
166  mOptListWidget->setMinimumWidth( newWidth );
167 
168  if ( iconOnly && ( diffWidth || mOptListWidget->width() != newWidth ) )
169  {
170  splitSizes[1] = splitSizes.at( 1 ) - ( splitSizes.at( 0 ) - newWidth );
171  splitSizes[0] = newWidth;
172  mOptSplitter->setSizes( splitSizes );
173  }
174  if ( mOptListWidget->wordWrap() && iconOnly )
175  mOptListWidget->setWordWrap( false );
176  if ( !mOptListWidget->wordWrap() && !iconOnly )
177  mOptListWidget->setWordWrap( true );
178 }
179 
181 {
182  mOptListWidget->blockSignals( true );
183  mOptListWidget->setCurrentRow( indx );
184  mOptListWidget->blockSignals( false );
185 }
186 
188 {
189  // will need to take item first, if widgets are set for item in future
190  delete mOptListWidget->item( indx );
191 }
192 
194 {
195  QMessageBox::warning( 0, tr( "Missing objects" ),
196  tr( "Base options dialog could not be initialized.\n\n"
197  "Missing some of the .ui template objects:\n" )
198  + " mOptionsListWidget,\n mOptionsStackedWidget,\n mOptionsSplitter",
199  QMessageBox::Ok,
200  QMessageBox::Ok );
201 }