mirror of
https://github.com/qgis/QGIS.git
synced 2025-04-14 00:07:35 -04:00
224 lines
7.8 KiB
C++
224 lines
7.8 KiB
C++
/***************************************************************************
|
|
qgsoptionsdialogbase.cpp - base vertical tabs option dialog
|
|
|
|
---------------------
|
|
begin : March 24, 2013
|
|
copyright : (C) 2013 by Larry Shaffer
|
|
email : larrys at dakcarto dot com
|
|
***************************************************************************
|
|
* *
|
|
* This program 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 of the License, or *
|
|
* (at your option) any later version. *
|
|
* *
|
|
***************************************************************************/
|
|
|
|
#include "qgsoptionsdialogbase.h"
|
|
|
|
#include <QDialog>
|
|
#include <QDialogButtonBox>
|
|
#include <QLayout>
|
|
#include <QListWidget>
|
|
#include <QMessageBox>
|
|
#include <QScrollBar>
|
|
#include <QSettings>
|
|
#include <QStackedWidget>
|
|
#include <QSplitter>
|
|
#include <QTimer>
|
|
|
|
|
|
QgsOptionsDialogBase::QgsOptionsDialogBase( QString settingsKey, QWidget* parent, Qt::WFlags fl )
|
|
: QDialog( parent, fl ), mOptsKey( settingsKey ), mInit( false )
|
|
{
|
|
}
|
|
|
|
QgsOptionsDialogBase::~QgsOptionsDialogBase()
|
|
{
|
|
if ( mInit )
|
|
{
|
|
QSettings settings;
|
|
settings.setValue( QString( "/Windows/%1/geometry" ).arg( mOptsKey ), saveGeometry() );
|
|
settings.setValue( QString( "/Windows/%1/splitState" ).arg( mOptsKey ), mOptSplitter->saveState() );
|
|
settings.setValue( QString( "/Windows/%1/tab" ).arg( mOptsKey ), mOptStackedWidget->currentIndex() );
|
|
}
|
|
}
|
|
|
|
void QgsOptionsDialogBase::initOptionsBase( bool restoreUi )
|
|
{
|
|
// don't add to dialog margins
|
|
// redefine now, or those in inherited .ui file will be added
|
|
if ( layout() )
|
|
{
|
|
layout()->setContentsMargins( 0, 0, 0, 0 ); // Qt default spacing
|
|
}
|
|
|
|
// start with copy of qgsoptionsdialog_template.ui to ensure existence of these objects
|
|
mOptListWidget = findChild<QListWidget*>( "mOptionsListWidget" );
|
|
QFrame* optionsFrame = findChild<QFrame*>( "mOptionsFrame" );
|
|
mOptStackedWidget = findChild<QStackedWidget*>( "mOptionsStackedWidget" );
|
|
mOptSplitter = findChild<QSplitter*>( "mOptionsSplitter" );
|
|
mOptButtonBox = findChild<QDialogButtonBox*>( "buttonBox" );
|
|
QFrame* buttonBoxFrame = findChild<QFrame*>( "mButtonBoxFrame" );
|
|
|
|
if ( !mOptListWidget || !mOptStackedWidget || !mOptSplitter || !optionsFrame )
|
|
{
|
|
return;
|
|
}
|
|
|
|
QSettings settings;
|
|
int size = settings.value( "/IconSize", 24 ).toInt();
|
|
mOptListWidget->setIconSize( QSize( size, size ) );
|
|
mOptListWidget->setFrameStyle( QFrame::NoFrame );
|
|
|
|
optionsFrame->layout()->setContentsMargins( 0, 3, 3, 3 );
|
|
QVBoxLayout* layout = static_cast<QVBoxLayout*>( optionsFrame->layout() );
|
|
|
|
if ( buttonBoxFrame )
|
|
{
|
|
buttonBoxFrame->layout()->setContentsMargins( 0, 0, 0, 0 );
|
|
layout->insertWidget( layout->count() + 1, buttonBoxFrame );
|
|
}
|
|
else
|
|
{
|
|
layout->insertWidget( layout->count() + 1, mOptButtonBox );
|
|
}
|
|
|
|
if ( mOptButtonBox )
|
|
{
|
|
// enforce only one connection per signal, in case added in Qt Designer
|
|
disconnect( mOptButtonBox, SIGNAL( accepted() ), this, SLOT( accept() ) );
|
|
connect( mOptButtonBox, SIGNAL( accepted() ), this, SLOT( accept() ) );
|
|
disconnect( mOptButtonBox, SIGNAL( rejected() ), this, SLOT( reject() ) );
|
|
connect( mOptButtonBox, SIGNAL( rejected() ), this, SLOT( reject() ) );
|
|
}
|
|
connect( mOptSplitter, SIGNAL( splitterMoved( int, int ) ), this, SLOT( updateOptionsListVerticalTabs() ) );
|
|
connect( mOptStackedWidget, SIGNAL( currentChanged( int ) ), this, SLOT( optionsStackedWidget_CurrentChanged( int ) ) );
|
|
connect( mOptStackedWidget, SIGNAL( widgetRemoved( int ) ), this, SLOT( optionsStackedWidget_WidgetRemoved( int ) ) );
|
|
|
|
mInit = true;
|
|
|
|
if ( restoreUi )
|
|
restoreOptionsBaseUi();
|
|
}
|
|
|
|
void QgsOptionsDialogBase::restoreOptionsBaseUi()
|
|
{
|
|
if ( !mInit )
|
|
{
|
|
return;
|
|
}
|
|
|
|
QSettings settings;
|
|
restoreGeometry( settings.value( QString( "/Windows/%1/geometry" ).arg( mOptsKey ) ).toByteArray() );
|
|
// mOptListWidget width is fixed to take up less space in QtDesigner
|
|
// revert it now unless the splitter's state hasn't been saved yet
|
|
mOptListWidget->setMaximumWidth(
|
|
settings.value( QString( "/Windows/%1/splitState" ).arg( mOptsKey ) ).isNull() ? 150 : 16777215 );
|
|
mOptSplitter->restoreState( settings.value( QString( "/Windows/%1/splitState" ).arg( mOptsKey ) ).toByteArray() );
|
|
int curIndx = settings.value( QString( "/Windows/%1/tab" ).arg( mOptsKey ), 0 ).toInt();
|
|
|
|
// if the last used tab is out of range or not enabled display the first enabled one
|
|
if ( mOptStackedWidget->count() < ( curIndx + 1 )
|
|
|| !mOptStackedWidget->widget( curIndx )->isEnabled() )
|
|
{
|
|
curIndx = 0;
|
|
for ( int i = 0; i < mOptStackedWidget->count(); i++ )
|
|
{
|
|
if ( mOptStackedWidget->widget( i )->isEnabled() )
|
|
{
|
|
curIndx = i;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( mOptStackedWidget->count() != 0 && mOptListWidget->count() != 0 )
|
|
{
|
|
mOptStackedWidget->setCurrentIndex( curIndx );
|
|
mOptListWidget->setCurrentRow( curIndx );
|
|
}
|
|
|
|
// get rid of annoying outer focus rect on Mac
|
|
mOptListWidget->setAttribute( Qt::WA_MacShowFocusRect, false );
|
|
}
|
|
|
|
void QgsOptionsDialogBase::showEvent( QShowEvent* e )
|
|
{
|
|
if ( mInit )
|
|
{
|
|
updateOptionsListVerticalTabs();
|
|
}
|
|
else
|
|
{
|
|
QTimer::singleShot( 0, this, SLOT( warnAboutMissingObjects() ) );
|
|
}
|
|
|
|
QDialog::showEvent( e );
|
|
}
|
|
|
|
void QgsOptionsDialogBase::paintEvent( QPaintEvent* e )
|
|
{
|
|
if ( mInit )
|
|
QTimer::singleShot( 0, this, SLOT( updateOptionsListVerticalTabs() ) );
|
|
|
|
QDialog::paintEvent( e );
|
|
}
|
|
|
|
void QgsOptionsDialogBase::updateOptionsListVerticalTabs()
|
|
{
|
|
if ( !mInit )
|
|
return;
|
|
|
|
if ( mOptListWidget->maximumWidth() != 16777215 )
|
|
mOptListWidget->setMaximumWidth( 16777215 );
|
|
// auto-resize splitter for vert scrollbar without covering icons in icon-only mode
|
|
// TODO: mOptListWidget has fixed 32px wide icons for now, allow user-defined
|
|
// Note: called on splitter resize and dialog paint event, so only update when necessary
|
|
int iconWidth = mOptListWidget->iconSize().width();
|
|
int snapToIconWidth = iconWidth + 32;
|
|
|
|
QList<int> splitSizes = mOptSplitter->sizes();
|
|
bool iconOnly = ( splitSizes.at( 0 ) <= snapToIconWidth );
|
|
|
|
int newWidth = mOptListWidget->verticalScrollBar()->isVisible() ? iconWidth + 26 : iconWidth + 12;
|
|
bool diffWidth = mOptListWidget->minimumWidth() != newWidth;
|
|
|
|
if ( diffWidth )
|
|
mOptListWidget->setMinimumWidth( newWidth );
|
|
|
|
if ( iconOnly && ( diffWidth || mOptListWidget->width() != newWidth ) )
|
|
{
|
|
splitSizes[1] = splitSizes.at( 1 ) - ( splitSizes.at( 0 ) - newWidth );
|
|
splitSizes[0] = newWidth;
|
|
mOptSplitter->setSizes( splitSizes );
|
|
}
|
|
if ( mOptListWidget->wordWrap() && iconOnly )
|
|
mOptListWidget->setWordWrap( false );
|
|
if ( !mOptListWidget->wordWrap() && !iconOnly )
|
|
mOptListWidget->setWordWrap( true );
|
|
}
|
|
|
|
void QgsOptionsDialogBase::optionsStackedWidget_CurrentChanged( int indx )
|
|
{
|
|
mOptListWidget->blockSignals( true );
|
|
mOptListWidget->setCurrentRow( indx );
|
|
mOptListWidget->blockSignals( false );
|
|
}
|
|
|
|
void QgsOptionsDialogBase::optionsStackedWidget_WidgetRemoved( int indx )
|
|
{
|
|
// will need to take item first, if widgets are set for item in future
|
|
delete mOptListWidget->item( indx );
|
|
}
|
|
|
|
void QgsOptionsDialogBase::warnAboutMissingObjects()
|
|
{
|
|
QMessageBox::warning( 0, tr( "Missing objects" ),
|
|
tr( "Base options dialog could not be initialized.\n\n"
|
|
"Missing some of the .ui template objects:\n" )
|
|
+ " mOptionsListWidget,\n mOptionsStackedWidget,\n mOptionsSplitter",
|
|
QMessageBox::Ok,
|
|
QMessageBox::Ok );
|
|
}
|