All customization and QGIS browser work in one commit.

This commit is contained in:
Martin Dobias 2011-05-13 22:00:46 +02:00
parent c087409a7a
commit 153ad164fe
129 changed files with 9316 additions and 699 deletions

0
dbl.txt Normal file
View File

View File

@ -178,6 +178,8 @@
<file>themes/default/mIconTableLayer.png</file>
<file>themes/default/mIconUnknownLayerType.png</file>
<file>themes/default/mIconWaitingForLayerType.png</file>
<file>themes/default/mIconWms.png</file>
<file>themes/default/mIconWmsLayer.png</file>
<file>themes/default/mMapserverExport.png</file>
<file>themes/default/plugin.png</file>
<file>themes/default/propertyicons/action.png</file>

BIN
images/splash/deblin.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 277 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 426 KiB

After

Width:  |  Height:  |  Size: 277 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 426 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 968 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 817 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 518 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 853 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 672 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 978 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1003 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 638 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 749 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 966 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 721 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 439 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 702 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 408 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 729 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 164 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 953 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 555 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 287 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 405 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 797 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 756 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 643 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 807 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 559 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 408 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 586 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 548 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 686 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 680 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 623 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 483 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 572 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 823 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 783 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 314 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 415 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 726 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 677 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 716 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 828 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 898 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

129
python/widgets_tree.py Executable file
View File

@ -0,0 +1,129 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# 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.
"""
Reads .ui files from ../src/ui/ directory and write to stdout an XML describing
widgets tree.
Python bindings must be compiled and in PYTHONPATH
QGIS libraries must be in LD_LIBRARY_PATH
Output should go to ../resources/customization.xml
"""
import sys
import os, glob, imp
from PyQt4.QtGui import *
from PyQt4.uic import loadUi, compileUi
from xml.etree.ElementTree import Element, SubElement, Comment, tostring
from xml.dom import minidom
# qwt_plot is missing somehow but it may depend on installed packages
from PyQt4 import Qwt5 as qwt_plot
sys.modules['qwt_plot'] = qwt_plot
# loadUi is looking for custom widget in module which is lowercase version of
# the class, which do not exist (AFAIK) -> preload them, problems anyway:
# missing in gui: QgsColorRampComboBox, QgsRendererRulesTreeWidget,
# QgsRendererRulesTreeWidget, QgsAttributeTableView
# and QgsProjectionSelector cannot open db file
from qgis import gui
for m in ['qgscolorbutton', 'qgscolorrampcombobox', 'qgsprojectionselector', 'qgslabelpreview', 'qgsrulebasedrendererv2widget', 'qgsattributetableview' ]:
sys.modules[m] = gui
class UiInspector:
def __init__(self ):
self.ui_dir = os.path.abspath ( os.path.join( os.path.dirname(__file__) , '../src/ui/*.ui' ) )
self.printMsg ( "Loading UI files " + self.ui_dir )
# list of widget classes we want to follow
self.follow = [
QWidget, QDialog,
QCheckBox, QComboBox, QDial, QPushButton, QLabel, QLCDNumber, QLineEdit, QRadioButton, QScrollBar, QSlider, QSpinBox, QTextEdit,
QDateEdit, QTimeEdit, QDateTimeEdit, QListView, QProgressBar, QTableView, QTabWidget, QTextBrowser, QDialogButtonBox,
QScrollArea, QGroupBox, QStackedWidget,
]
def printMsg ( self, msg ):
sys.stderr.write( msg + "\n" )
def widgetXml(self, element, widget, level = 0, label = None ):
#print tostring ( element )
#self.printMsg ( "class: " + str( type ( widget ) ) )
#self.printMsg ( "objectName: " + widget.objectName() )
#self.printMsg ( "windowTitle: " + widget.windowTitle() )
if not widget.objectName(): return
lab = label
if hasattr( widget, 'text' ):
lab = widget.text()
if widget.windowTitle():
label = widget.windowTitle()
if not lab:
lab = ''
lab = unicode(lab).encode("ascii","replace")
sub_element = SubElement( element, 'widget')
sub_element.set('class', widget.__class__.__name__ )
sub_element.set('objectName', widget.objectName() )
sub_element.set('label', lab )
#print str ( widget.children () )
# tab widget label is stored in QTabWidget->QTabBarPrivate->tabList->QTab ..
if type(widget) in [ QTabWidget ]:
children = list ( { 'widget': widget.widget(i), 'label': widget.tabText(i) } for i in range ( 0, widget.count() ) )
else:
children = list ( { 'widget': c, 'label': None } for c in widget.children () )
for child in children:
w = child['widget']
if w.isWidgetType() and ( type(w) in self.follow ):
self.widgetXml ( sub_element, w, level+1, child['label'] )
def treeXml(self, element ):
xml = ''
# debug
for p in glob.glob( self.ui_dir ):
#for p in ['/home/radim/devel/qgis_trunk/src/ui/qgsabout.ui']:
#for p in ['/home/radim/devel/qgis_trunk/src/ui/qgsrasterlayerpropertiesbase.ui']:
self.printMsg ( "Loading " + p )
# qgsrasterlayerpropertiesbase.ui is giving: No module named qwt_plot
try:
widget = loadUi ( p )
#print dir ( ui )
self.widgetXml ( element, widget )
except Exception, e:
#except IOError, e:
self.printMsg ( str(e) )
return xml
def xml( self ) :
#xml = "<?xml version='1.0' encoding='UTF-8'?>\n"
#xml += "<!DOCTYPE qgiswidgets SYSTEM 'http://mrcc.com/qgiswidgets.dtd'>\n"
element = Element('qgiswidgets')
self.treeXml( element )
string = tostring ( element, 'utf-8' )
reparsed = minidom.parseString(string)
xml = reparsed.toprettyxml(indent=" ")
return xml
if __name__ == '__main__':
app = QApplication(sys.argv) # required by loadUi
inspector = UiInspector()
xml = inspector.xml()
sys.stdout.write( xml )
sys.stdout.flush()
del app
sys.exit(0)

View File

@ -1,5 +1,5 @@
INSTALL(FILES srs.db qgis.db qgis_help.db symbology-ng-style.xml spatialite.db
INSTALL(FILES srs.db qgis.db qgis_help.db symbology-ng-style.xml spatialite.db customization.xml customization.ini
DESTINATION ${QGIS_DATA_DIR}/resources)
SUBDIRS(context_help)

1832
resources/customization.ini Normal file

File diff suppressed because it is too large Load Diff

2024
resources/customization.xml Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,4 @@
SUBDIRS(astyle core analysis ui gui app providers plugins helpviewer)
SUBDIRS(astyle core analysis ui gui app providers plugins helpviewer browser)
IF (WITH_BINDINGS)
SUBDIRS(python)

View File

@ -16,6 +16,7 @@ SET(QGIS_APP_SRCS
qgsclipboard.cpp
qgscontinuouscolordialog.cpp
qgsconfigureshortcutsdialog.cpp
qgscustomization.cpp
qgscustomprojectiondialog.cpp
qgsdbfilterproxymodel.cpp
qgsdbtablemodel.cpp
@ -23,7 +24,6 @@ SET(QGIS_APP_SRCS
qgsdelattrdialog.cpp
qgsdisplayangle.cpp
qgsfieldcalculator.cpp
qgsnewvectorlayerdialog.cpp
qgsgraduatedsymboldialog.cpp
qgsidentifyresults.cpp
qgsfeatureaction.cpp
@ -67,8 +67,6 @@ SET(QGIS_APP_SRCS
qgsmeasuredialog.cpp
qgsmeasuretool.cpp
qgsmergeattributesdialog.cpp
qgsnewhttpconnection.cpp
qgsnumericsortlistviewitem.cpp
qgsoptions.cpp
qgspastetransformations.cpp
qgspointrotationitem.cpp
@ -80,7 +78,6 @@ SET(QGIS_APP_SRCS
qgsrastercalcdialog.cpp
qgsrasterlayerproperties.cpp
qgstextannotationdialog.cpp
qgswmssourceselect.cpp
qgsshortcutsmanager.cpp
qgssinglesymboldialog.cpp
qgssnappingdialog.cpp
@ -94,7 +91,6 @@ SET(QGIS_APP_SRCS
qgshighlight.cpp
qgshandlebadlayers.cpp
qgsmanageconnectionsdialog.cpp
composer/qgsattributeselectiondialog.cpp
composer/qgscomposer.cpp
@ -131,12 +127,6 @@ SET(QGIS_APP_SRCS
ogr/qgsvectorlayersaveasdialog.cpp
attributetable/qgsattributetabledialog.cpp
attributetable/qgsattributetablemodel.cpp
attributetable/qgsattributetablememorymodel.cpp
attributetable/qgsattributetableview.cpp
attributetable/qgsattributetablefiltermodel.cpp
attributetable/qgsattributetableidcolumnpair.cpp
attributetable/qgsattributetabledelegate.cpp
gps/qgsgpsinformationwidget.cpp
gps/qgsgpsmarker.cpp
@ -157,6 +147,7 @@ SET (QGIS_APP_MOC_HDRS
qgsbookmarks.h
qgsconfigureshortcutsdialog.h
qgscontinuouscolordialog.h
qgscustomization.h
qgscustomprojectiondialog.h
qgsdbtablemodel.h
qgsdelattrdialog.h
@ -170,7 +161,6 @@ SET (QGIS_APP_MOC_HDRS
qgslabelengineconfigdialog.h
qgslabelinggui.h
qgslabelpropertydialog.h
qgsmanageconnectionsdialog.h
qgsmaptooladdfeature.h
qgsmaptooladdisland.h
qgsmaptooladdring.h
@ -199,8 +189,6 @@ SET (QGIS_APP_MOC_HDRS
qgsmeasuredialog.h
qgsmeasuretool.h
qgsmergeattributesdialog.h
qgsnewhttpconnection.h
qgsnewvectorlayerdialog.h
qgsoptions.h
qgspastetransformations.h
qgspluginmanager.h
@ -218,7 +206,6 @@ SET (QGIS_APP_MOC_HDRS
qgsundowidget.h
qgsuniquevaluedialog.h
qgsvectorlayerproperties.h
qgswmssourceselect.h
qgshandlebadlayers.h
composer/qgsattributeselectiondialog.h
@ -245,11 +232,7 @@ SET (QGIS_APP_MOC_HDRS
ogr/qgsogrsublayersdialog.h
ogr/qgsvectorlayersaveasdialog.h
attributetable/qgsattributetableview.h
attributetable/qgsattributetablemodel.h
attributetable/qgsattributetablememorymodel.h
attributetable/qgsattributetabledialog.h
attributetable/qgsattributetabledelegate.h
gps/qgsgpsinformationwidget.h
)
@ -364,7 +347,7 @@ INCLUDE_DIRECTORIES(
../core
../core/gps ../core/gps/qextserialport
../core/composer ../core/raster ../core/renderer ../core/symbology ../core/symbology-ng
../gui ../gui/symbology-ng
../gui ../gui/symbology-ng ../gui/attributetable
../plugins
../python
gps

View File

@ -35,6 +35,7 @@
#include "qgsmapcanvas.h"
#include "qgsfieldcalculator.h"
#include "qgsfeatureaction.h"
#include "qgsattributeaction.h"
class QgsAttributeTableDock : public QDockWidget
{
@ -64,6 +65,10 @@ QgsAttributeTableDialog::QgsAttributeTableDialog( QgsVectorLayer *theLayer, QWid
QSettings settings;
restoreGeometry( settings.value( "/Windows/BetterAttributeTable/geometry" ).toByteArray() );
// extent has to be set before the model is created
QgsAttributeTableModel::setCurrentExtent( QgisApp::instance()->mapCanvas()->extent() );
connect( QgisApp::instance()->mapCanvas(), SIGNAL( extentsChanged() ), this, SLOT( updateExtent() ) );
mView->setLayer( mLayer );
mFilterModel = ( QgsAttributeTableFilterModel * ) mView->model();
mModel = ( QgsAttributeTableModel * )(( QgsAttributeTableFilterModel * )mView->model() )->sourceModel();
@ -126,10 +131,7 @@ QgsAttributeTableDialog::QgsAttributeTableDialog( QgsVectorLayer *theLayer, QWid
connect( mView->verticalHeader(), SIGNAL( sectionPressed( int ) ), this, SLOT( updateRowPressed( int ) ) );
connect( mModel, SIGNAL( modelChanged() ), this, SLOT( updateSelection() ) );
if ( settings.value( "/qgis/attributeTableBehaviour", 0 ).toInt() == 2 )
{
connect( QgisApp::instance()->mapCanvas(), SIGNAL( extentsChanged() ), mModel, SLOT( layerModified() ) );
}
connect( mView, SIGNAL(willShowContextMenu( QMenu*, QModelIndex ) ), this, SLOT(viewWillShowContextMenu(QMenu*, QModelIndex ) ) );
mLastClickedHeaderIndex = 0;
mSelectionModel = new QItemSelectionModel( mFilterModel );
@ -241,19 +243,7 @@ void QgsAttributeTableDialog::on_mCopySelectedRowsButton_clicked()
void QgsAttributeTableDialog::on_mZoomMapToSelectedRowsButton_clicked()
{
QSettings settings;
bool canvasFeatures = settings.value( "/qgis/attributeTableBehaviour", 0 ).toInt() == 2;
if ( canvasFeatures )
{
disconnect( QgisApp::instance()->mapCanvas(), SIGNAL( extentsChanged() ), mModel, SLOT( layerModified() ) );
}
QgisApp::instance()->mapCanvas()->zoomToSelected( mLayer );
if ( canvasFeatures )
{
connect( QgisApp::instance()->mapCanvas(), SIGNAL( extentsChanged() ), mModel, SLOT( layerModified() ) );
}
}
void QgsAttributeTableDialog::on_mInvertSelectionButton_clicked()
@ -821,3 +811,49 @@ void QgsAttributeTableDialog::addFeature()
mModel->reload( mModel->index( 0, 0 ), mModel->index( mModel->rowCount(), mModel->columnCount() ) );
}
}
void QgsAttributeTableDialog::updateExtent()
{
// let the model know about the new extent (we may be showing only features from current extent)
QgsAttributeTableModel::setCurrentExtent( QgisApp::instance()->mapCanvas()->extent() );
}
void QgsAttributeTableDialog::viewWillShowContextMenu( QMenu* menu, QModelIndex atIndex )
{
if ( mLayer->actions()->size() != 0 )
{
QAction *a = menu->addAction( tr( "Run action" ) );
a->setEnabled( false );
for ( int i = 0; i < mLayer->actions()->size(); i++ )
{
const QgsAction &action = mLayer->actions()->at( i );
if ( !action.runable() )
continue;
QgsAttributeTableAction *a = new QgsAttributeTableAction( action.name(), mView, mModel, i, atIndex );
menu->addAction( action.name(), a, SLOT( execute() ) );
}
}
QgsAttributeTableAction *a = new QgsAttributeTableAction( tr( "Open form" ), mView, mModel, -1, atIndex );
menu->addAction( tr( "Open form" ), a, SLOT( featureForm() ) );
}
void QgsAttributeTableAction::execute()
{
mModel->executeAction( mAction, mFieldIdx );
}
void QgsAttributeTableAction::featureForm()
{
QgsFeature f = mModel->feature( mFieldIdx );
QgsFeatureAction action( tr( "Attributes changed" ), f, mModel->layer(), -1, this );
if ( mModel->layer()->isEditable() )
action.editFeature();
else
action.viewFeatureForm();
}

View File

@ -58,6 +58,10 @@ class QgsAttributeTableDialog : public QDialog, private Ui::QgsAttributeTableDia
*/
void editingToggled();
void updateExtent();
void viewWillShowContextMenu( QMenu* menu, QModelIndex atIndex );
private slots:
/**
* submits the data
@ -213,4 +217,25 @@ class QgsAttributeTableDialog : public QDialog, private Ui::QgsAttributeTableDia
QDockWidget *mDock;
};
class QgsAttributeTableAction : public QAction
{
Q_OBJECT
public:
QgsAttributeTableAction( const QString &name, QgsAttributeTableView *view, QgsAttributeTableModel *model, int action, const QModelIndex &fieldIdx ) :
QAction( name, view ), mModel( model ), mAction( action ), mFieldIdx( fieldIdx )
{}
public slots:
void execute();
void featureForm();
private:
QgsAttributeTableModel *mModel;
int mAction;
QModelIndex mFieldIdx;
};
#endif

View File

@ -34,6 +34,7 @@
#include <QTranslator>
#include <QImageReader>
#include "qgscustomization.h"
#include "qgspluginregistry.h"
#include <cstdio>
@ -67,6 +68,7 @@ typedef SInt32 SRefCon;
#include "qgsmapcanvas.h"
#include "qgsapplication.h"
#include <qgsconfig.h>
#include <qgscustomization.h>
#include <qgssvnversion.h>
#include "qgsexception.h"
#include "qgsproject.h"
@ -99,6 +101,7 @@ void usage( std::string const & appName )
<< "\t[--extent xmin,ymin,xmax,ymax]\tset initial map extent\n"
<< "\t[--nologo]\thide splash screen\n"
<< "\t[--noplugins]\tdon't restore plugins on startup\n"
<< "\t[--nocustomization]\tdon't apply GUI customization\n"
<< "\t[--optionspath path]\tuse the given QSettings path\n"
<< "\t[--configpath path]\tuse the given path for all user configuration\n"
<< "\t[--help]\t\tthis text\n\n"
@ -212,6 +215,7 @@ int main( int argc, char *argv[] )
bool myHideSplash = false;
bool myRestorePlugins = true;
bool myCustomization = true;
// This behaviour will set initial extent of map canvas, but only if
// there are no command line arguments. This gives a usable map
@ -246,6 +250,7 @@ int main( int argc, char *argv[] )
{"help", no_argument, 0, '?'},
{"nologo", no_argument, 0, 'n'},
{"noplugins", no_argument, 0, 'P'},
{"nocustomization", no_argument, 0, 'C'},
/* These options don't set a flag.
* We distinguish them by their indices. */
{"snapshot", required_argument, 0, 's'},
@ -309,6 +314,10 @@ int main( int argc, char *argv[] )
myRestorePlugins = false;
break;
case 'C':
myCustomization = false;
break;
case 'e':
myInitialExtent = optarg;
break;
@ -365,6 +374,10 @@ int main( int argc, char *argv[] )
{
myRestorePlugins = false;
}
else if ( arg == "--nocustomization" || arg == "-C" )
{
myCustomization = false;
}
else if ( i + 1 < argc && ( arg == "--snapshot" || arg == "-s" ) )
{
mySnapshotFileName = QDir::convertSeparators( QFileInfo( QFile::decodeName( argv[++i] ) ).absoluteFilePath() );
@ -434,6 +447,9 @@ int main( int argc, char *argv[] )
QSettings::setPath( QSettings::IniFormat, QSettings::UserScope, configpath );
}
// GUI customization is enabled by default unless --nocustomization argument is used
QgsCustomization::instance()->setEnabled(myCustomization);
QgsApplication myApp( argc, argv, myUseGuiFlag, configpath );
// (if Windows/Mac, use icon from resource)
@ -447,6 +463,10 @@ int main( int argc, char *argv[] )
QCoreApplication::setOrganizationDomain( "qgis.org" );
QCoreApplication::setApplicationName( "QGIS" );
QCoreApplication::setAttribute( Qt::AA_DontShowIconsInMenus, false );
// Load and set possible default customization, must be done afterQgsApplication init and QSettings ( QCoreApplication ) init
QgsCustomization::instance()->loadDefault();
#ifdef Q_OS_MACX
// If the GDAL plugins are bundled with the application and GDAL_DRIVER_PATH
// is not already defined, use the GDAL plugins in the application bundle.
@ -596,6 +616,12 @@ int main( int argc, char *argv[] )
QgisApp *qgis = new QgisApp( mypSplash, myRestorePlugins ); // "QgisApp" used to find canonical instance
qgis->setObjectName( "QgisApp" );
myApp.connect (
&myApp, SIGNAL( preNotify( QObject *, QEvent *, bool *)),
//qgis, SLOT( preNotify( QObject *, QEvent *))
QgsCustomization::instance(), SLOT( preNotify( QObject *, QEvent *, bool *))
);
/////////////////////////////////////////////////////////////////////
// If no --project was specified, parse the args to look for a //
// .qgs file and set myProjectFileName to it. This allows loading //

View File

@ -111,6 +111,7 @@
#include "qgscoordinatetransform.h"
#include "qgscredentialdialog.h"
#include "qgscursors.h"
#include "qgscustomization.h"
#include "qgscustomprojectiondialog.h"
#include "qgsdatasourceuri.h"
#include "qgsencodingfiledialog.h"
@ -145,6 +146,7 @@
#include "qgsproject.h"
#include "qgsprojectproperties.h"
#include "qgsproviderregistry.h"
#include "qgspythonrunner.h"
#include "qgsquerybuilder.h"
#include "qgsrastercalcdialog.h"
#include "qgsrasterlayer.h"
@ -162,7 +164,7 @@
#include "qgsvectorfilewriter.h"
#include "qgsvectorlayer.h"
#include "qgsvectorlayerproperties.h"
#include "qgswmssourceselect.h"
//#include "qgswmssourceselect.h"
#include "ogr/qgsogrsublayersdialog.h"
#include "ogr/qgsopenvectorlayerdialog.h"
#include "ogr/qgsvectorlayersaveasdialog.h"
@ -298,7 +300,7 @@ static void setTitleBarText_( QWidget & qgisApp )
{
caption += " - " + QgsProject::instance()->title();
}
caption = QgisApp::tr( "Quantum GIS pro Deblin" ); //for dbl
qgisApp.setWindowTitle( caption );
} // setTitleBarText_( QWidget * qgisApp )
@ -466,6 +468,7 @@ QgisApp::QgisApp( QSplashScreen *splash, bool restorePlugins, QWidget * parent,
// set graphical message output
QgsMessageOutput::setMessageOutputCreator( messageOutputViewer_ );
// set graphical credential requester
new QgsCredentialDialog( this );
@ -481,7 +484,6 @@ QgisApp::QgisApp( QSplashScreen *splash, bool restorePlugins, QWidget * parent,
qApp->processEvents();
loadPythonSupport();
// Create the plugin registry and load plugins
// load any plugins that were running in the last session
mSplash->showMessage( tr( "Restoring loaded plugins" ), Qt::AlignHCenter | Qt::AlignBottom );
@ -535,6 +537,9 @@ QgisApp::QgisApp( QSplashScreen *splash, bool restorePlugins, QWidget * parent,
qApp->processEvents();
restoreWindowState();
// do main window customization - after window state has been restored, before the window is shown
QgsCustomization::instance()->updateMainWindow();
mSplash->showMessage( tr( "QGIS Ready!" ), Qt::AlignHCenter | Qt::AlignBottom );
mMapTipsVisible = false;
@ -822,6 +827,7 @@ void QgisApp::createActions()
connect( mActionCustomProjection, SIGNAL( triggered() ), this, SLOT( customProjection() ) );
connect( mActionConfigureShortcuts, SIGNAL( triggered() ), this, SLOT( configureShortcuts() ) );
connect( mActionStyleManagerV2, SIGNAL( triggered() ), this, SLOT( showStyleManagerV2() ) );
connect( mActionCustomization, SIGNAL( triggered() ), this, SLOT( customize() ) );
#ifdef Q_WS_MAC
// Window Menu Items
@ -990,8 +996,9 @@ void QgisApp::createMenus()
// Panel and Toolbar Submenus
mPanelMenu = new QMenu( tr( "Panels" ) );
mPanelMenu->setObjectName("mPanelMenu");
mToolbarMenu = new QMenu( tr( "Toolbars" ) );
mToolbarMenu->setObjectName("mToolbarMenu");
// Get platform for menu layout customization (Gnome, Kde, Mac, Win)
QDialogButtonBox::ButtonLayout layout =
@ -1018,6 +1025,7 @@ void QgisApp::createMenus()
mEditMenu->addAction( mActionOptions );
mEditMenu->addAction( mActionSnappingOptions );
mEditMenu->addAction( mActionConfigureShortcuts );
mEditMenu->addAction( mActionCustomization );
mEditMenu->addAction( mActionStyleManagerV2 );
mEditMenu->addAction( mActionCustomProjection );
}
@ -1086,7 +1094,6 @@ void QgisApp::createToolBars()
// select tool button
QToolButton *bt = new QToolButton( mAttributesToolBar );
bt->setObjectName( "SelectTool" );
bt->setPopupMode( QToolButton::MenuButtonPopup );
QList<QAction*> selectActions;
selectActions << mActionSelect << mActionSelectRectangle << mActionSelectPolygon
@ -1103,14 +1110,13 @@ void QgisApp::createToolBars()
case 4: defSelectAction = mActionSelectRadius; break;
}
bt->setDefaultAction( defSelectAction );
mAttributesToolBar->insertWidget( mActionDeselectAll, bt );
QAction* selectAction = mAttributesToolBar->insertWidget( mActionDeselectAll, bt );
selectAction->setObjectName( "ActionSelect" );
connect( bt, SIGNAL( triggered( QAction * ) ), this, SLOT( toolButtonActionTriggered( QAction * ) ) );
// measure tool button
bt = new QToolButton( mAttributesToolBar );
bt->setObjectName( "MeasureTool" );
bt->setPopupMode( QToolButton::MenuButtonPopup );
bt->addAction( mActionMeasure );
bt->addAction( mActionMeasureArea );
@ -1124,13 +1130,13 @@ void QgisApp::createToolBars()
case 2: defMeasureAction = mActionMeasureAngle; break;
}
bt->setDefaultAction( defMeasureAction );
mAttributesToolBar->insertWidget( mActionMapTips, bt );
QAction* measureAction = mAttributesToolBar->insertWidget( mActionMapTips, bt );
measureAction->setObjectName( "ActionMeasure" );
connect( bt, SIGNAL( triggered( QAction * ) ), this, SLOT( toolButtonActionTriggered( QAction * ) ) );
// annotation tool button
bt = new QToolButton();
bt->setObjectName( "AnnotationTool" );
bt->setPopupMode( QToolButton::MenuButtonPopup );
bt->addAction( mActionTextAnnotation );
bt->addAction( mActionFormAnnotation );
@ -1144,7 +1150,8 @@ void QgisApp::createToolBars()
case 2: defAnnotationAction = mActionAnnotation; break;
}
bt->setDefaultAction( defAnnotationAction );
mAttributesToolBar->addWidget( bt );
QAction* annotationAction = mAttributesToolBar->addWidget( bt );
annotationAction->setObjectName( "ActionAnnotation" );
connect( bt, SIGNAL( triggered( QAction * ) ), this, SLOT( toolButtonActionTriggered( QAction * ) ) );
// Help Toolbar
@ -1160,6 +1167,7 @@ void QgisApp::createStatusBar()
// And also rendering suppression checkbox
//
mProgressBar = new QProgressBar( statusBar() );
mProgressBar->setObjectName( "mProgressBar" );
mProgressBar->setMaximumWidth( 100 );
mProgressBar->hide();
mProgressBar->setWhatsThis( tr( "Progress bar that displays the status "
@ -1173,6 +1181,7 @@ void QgisApp::createStatusBar()
statusBar()->setFont( myFont );
//toggle to switch between mouse pos and extents display in status bar widget
mToggleExtentsViewButton = new QToolButton( statusBar() );
mToggleExtentsViewButton->setObjectName( "mToggleExtentsViewButton" );
mToggleExtentsViewButton->setMaximumWidth( 20 );
mToggleExtentsViewButton->setMaximumHeight( 20 );
mToggleExtentsViewButton->setIcon( getThemeIcon( "tracking.png" ) );
@ -1183,6 +1192,7 @@ void QgisApp::createStatusBar()
// add a label to show current scale
mCoordsLabel = new QLabel( QString(), statusBar() );
mCoordsLabel->setObjectName( "mCoordsLabel" );
mCoordsLabel->setFont( myFont );
mCoordsLabel->setMinimumWidth( 10 );
mCoordsLabel->setMaximumHeight( 20 );
@ -1195,6 +1205,7 @@ void QgisApp::createStatusBar()
//coords status bar widget
mCoordsEdit = new QLineEdit( QString(), statusBar() );
mCoordsEdit->setObjectName( "mCoordsEdit" );
mCoordsEdit->setFont( myFont );
mCoordsEdit->setMinimumWidth( 10 );
mCoordsEdit->setMaximumWidth( 300 );
@ -1214,6 +1225,7 @@ void QgisApp::createStatusBar()
// add a label to show current scale
mScaleLabel = new QLabel( QString(), statusBar() );
mScaleLabel->setObjectName( "mScaleLable" );
mScaleLabel->setFont( myFont );
mScaleLabel->setMinimumWidth( 10 );
mScaleLabel->setMaximumHeight( 20 );
@ -1225,6 +1237,7 @@ void QgisApp::createStatusBar()
statusBar()->addPermanentWidget( mScaleLabel, 0 );
mScaleEdit = new QLineEdit( QString(), statusBar() );
mScaleEdit->setObjectName( "mScaleEdit" );
mScaleEdit->setFont( myFont );
mScaleEdit->setMinimumWidth( 10 );
mScaleEdit->setMaximumWidth( 100 );
@ -1242,6 +1255,7 @@ void QgisApp::createStatusBar()
//stop rendering status bar widget
mStopRenderButton = new QToolButton( statusBar() );
mStopRenderButton->setObjectName( "mStopRenderButton" );
mStopRenderButton->setMaximumWidth( 20 );
mStopRenderButton->setMaximumHeight( 20 );
mStopRenderButton->setIcon( getThemeIcon( "mIconStopRendering.png" ) );
@ -1249,6 +1263,7 @@ void QgisApp::createStatusBar()
statusBar()->addPermanentWidget( mStopRenderButton, 0 );
// render suppression status bar widget
mRenderSuppressionCBox = new QCheckBox( tr( "Render" ), statusBar() );
mRenderSuppressionCBox->setObjectName( "mRenderSuppressionCBox" );
mRenderSuppressionCBox->setChecked( true );
mRenderSuppressionCBox->setFont( myFont );
mRenderSuppressionCBox->setWhatsThis( tr( "When checked, the map layers "
@ -1259,6 +1274,7 @@ void QgisApp::createStatusBar()
statusBar()->addPermanentWidget( mRenderSuppressionCBox, 0 );
// On the fly projection active CRS label
mOnTheFlyProjectionStatusLabel = new QLabel( QString(), statusBar() );
mOnTheFlyProjectionStatusLabel->setObjectName( "mOnTheFlyProjectionStatusLabel" );
mOnTheFlyProjectionStatusLabel->setFont( myFont );
mOnTheFlyProjectionStatusLabel->setMinimumWidth( 10 );
mOnTheFlyProjectionStatusLabel->setMaximumHeight( 20 );
@ -1271,6 +1287,7 @@ void QgisApp::createStatusBar()
// Changed this to a tool button since a QPushButton is
// sculpted on OS X and the icon is never displayed [gsherman]
mOnTheFlyProjectionStatusButton = new QToolButton( statusBar() );
mOnTheFlyProjectionStatusButton->setObjectName( "mOntheFlyProjectionStatusButton" );
mOnTheFlyProjectionStatusButton->setMaximumWidth( 20 );
// Maintain uniform widget height in status bar by setting button height same as labels
// For Qt/Mac 3.3, the default toolbutton height is 30 and labels were expanding to match
@ -1362,6 +1379,7 @@ void QgisApp::setTheme( QString theThemeName )
mActionCheckQgisVersion->setIcon( getThemeIcon( "/mActionCheckQgisVersion.png" ) );
mActionOptions->setIcon( getThemeIcon( "/mActionOptions.png" ) );
mActionConfigureShortcuts->setIcon( getThemeIcon( "/mActionOptions.png" ) );
mActionCustomization->setIcon( getThemeIcon( "/mActionOptions.png" ) );
mActionHelpContents->setIcon( getThemeIcon( "/mActionHelpContents.png" ) );
mActionLocalHistogramStretch->setIcon( getThemeIcon( "/mActionLocalHistogramStretch.png" ) );
mActionFullHistogramStretch->setIcon( getThemeIcon( "/mActionFullHistogramStretch.png" ) );
@ -2456,7 +2474,17 @@ void QgisApp::addWmsLayer()
// Fudge for now
QgsDebugMsg( "about to addRasterLayer" );
QgsWMSSourceSelect *wmss = new QgsWMSSourceSelect( this );
// TODO: QDialog for now, switch to QWidget in future
QDialog *wmss = dynamic_cast<QDialog*> ( QgsProviderRegistry::instance()->getSelectWidget( QString("wms"), this ) );
if ( !wmss )
{
QMessageBox::warning( this, tr( "WMS" ), tr( "Cannot get WMS select dialog from provider." ) );
return;
}
connect ( wmss , SIGNAL ( addRasterLayer( QString const &, QString const &, QString const &,QStringList const &,QStringList const &,QString const &,
QString const &) ),
this , SLOT ( addRasterLayer( QString const &, QString const &, QString const &,QStringList const &,QStringList const &,QString const &,
QString const &) ) );
wmss->exec();
delete wmss;
}
@ -2585,96 +2613,17 @@ void QgisApp::newVectorLayer()
return;
}
QgsNewVectorLayerDialog geomDialog( this );
if ( geomDialog.exec() == QDialog::Rejected )
{
return;
}
QGis::WkbType geometrytype = geomDialog.selectedType();
QString fileformat = geomDialog.selectedFileFormat();
int crsId = geomDialog.selectedCrsId();
QgsDebugMsg( QString( "New file format will be: %1" ).arg( fileformat ) );
std::list<std::pair<QString, QString> > attributes;
geomDialog.attributes( attributes );
QString enc;
QString fileName;
QString fileName = QgsNewVectorLayerDialog::runAndCreateLayer( this, &enc );
QSettings settings;
QString lastUsedDir = settings.value( "/UI/lastVectorFileFilterDir", "." ).toString();
QgsDebugMsg( "Saving vector file dialog without filters: " );
QgsEncodingFileDialog* openFileDialog =
new QgsEncodingFileDialog( this, tr( "Save As" ), lastUsedDir, "", QString( "" ) );
openFileDialog->setFileMode( QFileDialog::AnyFile );
openFileDialog->setAcceptMode( QFileDialog::AcceptSave );
openFileDialog->setConfirmOverwrite( true );
if ( settings.contains( "/UI/lastVectorFileFilter" ) )
if ( !fileName.isEmpty() )
{
QString lastUsedFilter = settings.value( "/UI/lastVectorFileFilter", QVariant( QString::null ) ).toString();
openFileDialog->selectFilter( lastUsedFilter );
//then add the layer to the view
QStringList fileNames;
fileNames.append( fileName );
//todo: the last parameter will change accordingly to layer type
addVectorLayers( fileNames, enc, "file" );
}
if ( openFileDialog->exec() == QDialog::Rejected )
{
delete openFileDialog;
return;
}
fileName = openFileDialog->selectedFiles().first();
if ( fileformat == "ESRI Shapefile" && !fileName.endsWith( ".shp", Qt::CaseInsensitive ) )
fileName += ".shp";
enc = openFileDialog->encoding();
settings.setValue( "/UI/lastVectorFileFilter", openFileDialog->selectedFilter() );
settings.setValue( "/UI/lastVectorFileFilterDir", openFileDialog->directory().absolutePath() );
delete openFileDialog;
//try to create the new layer with OGRProvider instead of QgsVectorFileWriter
QgsProviderRegistry * pReg = QgsProviderRegistry::instance();
QString ogrlib = pReg->library( "ogr" );
// load the data provider
QLibrary* myLib = new QLibrary( ogrlib );
bool loaded = myLib->load();
if ( loaded )
{
QgsDebugMsg( "ogr provider loaded" );
typedef bool ( *createEmptyDataSourceProc )( const QString&, const QString&, const QString&, QGis::WkbType,
const std::list<std::pair<QString, QString> >&, const QgsCoordinateReferenceSystem * );
createEmptyDataSourceProc createEmptyDataSource = ( createEmptyDataSourceProc ) cast_to_fptr( myLib->resolve( "createEmptyDataSource" ) );
if ( createEmptyDataSource )
{
if ( geometrytype != QGis::WKBUnknown )
{
QgsCoordinateReferenceSystem srs( crsId, QgsCoordinateReferenceSystem::InternalCrsId );
createEmptyDataSource( fileName, fileformat, enc, geometrytype, attributes, &srs );
}
else
{
QgsDebugMsg( "geometry type not recognised" );
return;
}
}
else
{
QgsDebugMsg( "Resolving newEmptyDataSource(...) failed" );
}
}
//then add the layer to the view
QStringList fileNames;
fileNames.append( fileName );
//todo: the last parameter will change accordingly to layer type
addVectorLayers( fileNames, enc, "file" );
}
#ifdef HAVE_SPATIALITE
@ -4675,10 +4624,23 @@ void QgisApp::showPluginManager()
}
}
static void _runPythonString( const QString &expr )
// implementation of the python runner
class QgsPythonRunnerImpl : public QgsPythonRunner
{
QgisApp::instance()->runPythonString( expr );
}
public:
QgsPythonRunnerImpl(QgsPythonUtils* pythonUtils) : mPythonUtils(pythonUtils) {}
virtual bool runCommand( QString command, QString messageOnError = QString() )
{
if ( mPythonUtils && mPythonUtils->isEnabled() )
{
return mPythonUtils->runString( command, messageOnError );
}
return false;
}
protected:
QgsPythonUtils* mPythonUtils;
};
void QgisApp::loadPythonSupport()
{
@ -4724,7 +4686,9 @@ void QgisApp::loadPythonSupport()
if ( mPythonUtils && mPythonUtils->isEnabled() )
{
QgsPluginRegistry::instance()->setPythonUtils( mPythonUtils );
QgsAttributeAction::setPythonExecute( _runPythonString );
// init python runner
QgsPythonRunner::setInstance( new QgsPythonRunnerImpl(mPythonUtils) );
std::cout << "Python support ENABLED :-) " << std::endl; // OK
}
@ -4868,6 +4832,11 @@ void QgisApp::configureShortcuts()
dlg.exec();
}
void QgisApp::customize()
{
QgsCustomization::instance()->openDialog();
}
void QgisApp::options()
{
@ -6646,13 +6615,6 @@ void QgisApp::updateUndoActions()
mActionRedo->setEnabled( canRedo );
}
void QgisApp::runPythonString( const QString &expr )
{
if ( mPythonUtils && mPythonUtils->isEnabled() )
{
mPythonUtils->runString( expr );
}
}
// add project directory to python path
void QgisApp::projectChanged( const QDomDocument &doc )
@ -6678,7 +6640,7 @@ void QgisApp::projectChanged( const QDomDocument &doc )
expr += QString( "sys.path.append('%1')" ).arg( prevProjectDir );
runPythonString( expr );
QgsPythonRunner::run( expr );
}
void QgisApp::writeProject( QDomDocument &doc )

View File

@ -113,18 +113,6 @@ class QgisApp : public QMainWindow, private Ui::MainWindow
*/
bool addRasterLayers( QStringList const & theLayerQStringList, bool guiWarning = true );
/** Open a raster layer using the Raster Data Provider.
* Note this is included to support WMS layers only at this stage,
* GDAL layer support via a Provider is not yet implemented.
*/
QgsRasterLayer* addRasterLayer( QString const & rasterLayerPath,
QString const & baseName,
QString const & providerKey,
QStringList const & layers,
QStringList const & styles,
QString const & format,
QString const & crs );
/** open a raster layer for the given file
@returns false if unable to open a raster layer for rasterFile
@note
@ -345,9 +333,6 @@ class QgisApp : public QMainWindow, private Ui::MainWindow
QToolBar *helpToolBar() { return mHelpToolBar; }
QToolBar *rasterToolBar() { return mRasterToolBar; }
//! run python
void runPythonString( const QString &expr );
//! show layer properties
void showLayerProperties( QgsMapLayer *ml );
@ -436,6 +421,17 @@ class QgisApp : public QMainWindow, private Ui::MainWindow
//! Watch for QFileOpenEvent.
virtual bool event( QEvent * event );
/** Open a raster layer using the Raster Data Provider.
* Note this is included to support WMS layers only at this stage,
* GDAL layer support via a Provider is not yet implemented.
*/
QgsRasterLayer* addRasterLayer( QString const & rasterLayerPath,
QString const & baseName,
QString const & providerKey,
QStringList const & layers,
QStringList const & styles,
QString const & format,
QString const & crs );
protected:
//! Handle state changes (WindowTitleChange)
@ -590,6 +586,8 @@ class QgisApp : public QMainWindow, private Ui::MainWindow
void customProjection();
//! configure shortcuts
void configureShortcuts();
//! show customization dialog
void customize();
//! options dialog slot
void options();
//! Whats-this help slot

View File

@ -27,6 +27,7 @@
#include "qgshighlight.h"
#include "qgssearchstring.h"
#include "qgssearchtreenode.h"
#include "qgspythonrunner.h"
#include "qgisapp.h"
@ -282,15 +283,15 @@ QgsAttributeDialog::QgsAttributeDialog( QgsVectorLayer *vl, QgsFeature *thepFeat
int pos = module.lastIndexOf( "." );
if ( pos >= 0 )
{
QgisApp::instance()->runPythonString( QString( "import %1" ).arg( module.left( pos ) ) );
QgsPythonRunner::run( QString( "import %1" ).arg( module.left( pos ) ) );
}
mFormNr = smFormCounter++;
QgisApp::instance()->runPythonString( QString( "_qgis_featureform_%1 = wrapinstance( %2, QtGui.QDialog )" ).arg( mFormNr ).arg(( unsigned long ) mDialog ) );
QgsPythonRunner::run( QString( "_qgis_featureform_%1 = wrapinstance( %2, QtGui.QDialog )" ).arg( mFormNr ).arg(( unsigned long ) mDialog ) );
QString expr = QString( "%1(_qgis_featureform_%2,'%3',%4)" ).arg( vl->editFormInit() ).arg( mFormNr ).arg( vl->id() ).arg( mFeature->id() );
QgsDebugMsg( QString( "running featureForm init: %1" ).arg( expr ) );
QgisApp::instance()->runPythonString( expr );
QgsPythonRunner::run( expr );
}
restoreGeometry();
@ -401,7 +402,7 @@ void QgsAttributeDialog::dialogDestroyed()
if ( -1 < mFormNr )
{
QString expr = QString( "if locals().has_key('_qgis_featureform_%1'): del _qgis_featureform_%1\n" ).arg( mFormNr );
QgisApp::instance()->runPythonString( expr );
QgsPythonRunner::run( expr );
}
mDialog = NULL;

View File

@ -0,0 +1,897 @@
/***************************************************************************
qgscustomization.cpp - Customization
-------------------
begin : 2011-04-01
copyright : (C) 2011 Radim Blazek
email : radim dot blazek at gmail 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. *
* *
***************************************************************************/
/* $Id$ */
#include "qgscustomization.h"
#include "qgisapp.h"
#include "qgsapplication.h"
#include "qgslogger.h"
#include <QAction>
#include <QDir>
#include <QDockWidget>
#include <QDomDocument>
#include <QDomElement>
#include <QDomNode>
#include <QFile>
#include <QFileDialog>
#include <QFileInfo>
#include <QMessageBox>
#include <QSettings>
#include <QPushButton>
#include <QKeySequence>
#include <QToolButton>
#include <QStatusBar>
//standard includes
#include <cassert>
#include <fstream>
#include <typeinfo>
#ifdef Q_OS_MACX
QgsCustomizationDialog::QgsCustomizationDialog()
: QMainWindow( NULL, Qt::WindowSystemMenuHint ), // Modeless dialog with close button only
mSettings ( "QuantumGIS", "QGISCUSTOMIZATION" )
#else
QgsCustomizationDialog::QgsCustomizationDialog()
: QMainWindow( NULL ), mSettings ( "QuantumGIS", "QGISCUSTOMIZATION" )
#endif
{
setupUi( this );
init();
QStringList myHeaders;
myHeaders << tr("Object name") << tr("Label") << tr("Description");
treeWidget->setHeaderLabels ( myHeaders );
mLastDirSettingsName = QString("/UI/lastCustomizationDir" );
//treeWidget->hideColumn(0)
connect( buttonBox->button( QDialogButtonBox::Ok ), SIGNAL( clicked() ), this, SLOT( ok() ) );
connect( buttonBox->button( QDialogButtonBox::Apply ), SIGNAL( clicked() ), this, SLOT( apply() ) );
connect( buttonBox->button( QDialogButtonBox::Cancel ), SIGNAL( clicked() ), this, SLOT( cancel() ) );
connect( buttonBox->button( QDialogButtonBox::Reset ), SIGNAL( clicked() ), this, SLOT( reset() ) );
}
QgsCustomizationDialog::~QgsCustomizationDialog()
{
}
QTreeWidgetItem * QgsCustomizationDialog::item ( QString thePath, QTreeWidgetItem *theItem )
{
QString path = thePath;
if ( path.startsWith("/") ) path = path.mid(1); // remove '/'
QStringList names = path.split('/');
path = QStringList(names.mid(1)).join ("/" );
if ( ! theItem )
{
for (int i = 0; i < treeWidget->topLevelItemCount(); ++i)
{
QTreeWidgetItem *myItem = treeWidget->topLevelItem(i);
QString objectName = myItem->text(0);
if ( objectName == names[0] )
{
return item ( path, myItem );
}
}
}
else
{
for (int i = 0; i < theItem->childCount(); ++i) {
QTreeWidgetItem *myItem = theItem->child(i);
QString objectName = myItem->text(0);
if ( objectName == names[0] )
{
if ( names.size () == 1 )
{
return myItem;
}
else
{
return item ( path, myItem );
}
}
}
}
QgsDebugMsg( "not found") ;
return 0;
}
bool QgsCustomizationDialog::itemChecked ( QString thePath )
{
QgsDebugMsg( QString("thePath = %1").arg(thePath));
QTreeWidgetItem *myItem = item ( thePath );
if ( !myItem ) return true;
return myItem->checkState(0) == Qt::Checked ? true : false;
}
void QgsCustomizationDialog::setItemChecked ( QString thePath, bool on )
{
QgsDebugMsg( QString("thePath = %1 on = %2").arg(thePath).arg(on));
QTreeWidgetItem *myItem = item ( thePath );
if ( !myItem ) return;
myItem->setCheckState(0, on ? Qt::Checked : Qt::Unchecked);
}
void QgsCustomizationDialog::settingsToItem( QString thePath, QTreeWidgetItem *theItem, QSettings *theSettings )
{
QString objectName = theItem->text(0);
if (objectName.isEmpty())
return; // object is not identifiable
QString myPath = thePath + "/" + objectName;
bool on = theSettings->value(myPath, true).toBool();
theItem->setCheckState(0, on ? Qt::Checked : Qt::Unchecked );
for (int i = 0; i < theItem->childCount(); ++i) {
QTreeWidgetItem *myItem = theItem->child(i);
settingsToItem( myPath, myItem, theSettings );
}
}
void QgsCustomizationDialog::itemToSettings( QString thePath, QTreeWidgetItem *theItem, QSettings *theSettings )
{
QString objectName = theItem->text(0);
if (objectName.isEmpty())
return; // object is not identifiable
QString myPath = thePath + "/" + objectName;
bool on = theItem->checkState(0) == Qt::Checked ? true : false;
theSettings->setValue( myPath, on );
for (int i = 0; i < theItem->childCount(); ++i) {
QTreeWidgetItem *myItem = theItem->child(i);
itemToSettings( myPath, myItem, theSettings );
}
}
void QgsCustomizationDialog::treeToSettings ( QSettings *theSettings )
{
for (int i = 0; i < treeWidget->topLevelItemCount(); ++i) {
itemToSettings( QString("/Customization"), treeWidget->topLevelItem(i), theSettings );
}
}
void QgsCustomizationDialog::settingsToTree ( QSettings *theSettings )
{
for (int i = 0; i < treeWidget->topLevelItemCount(); ++i)
{
settingsToItem( QString("/Customization"), treeWidget->topLevelItem(i), theSettings );
}
}
void QgsCustomizationDialog::reset()
{
mSettings.sync();
settingsToTree ( &mSettings );
}
void QgsCustomizationDialog::ok()
{
apply();
hide();
}
void QgsCustomizationDialog::apply()
{
QgsDebugMsg( QString("columnCount = %1").arg( treeWidget->columnCount() ) );
treeToSettings ( &mSettings );
mSettings.setValue( QgsCustomization::instance()->statusPath(), QgsCustomization::User);
mSettings.sync();
}
void QgsCustomizationDialog::cancel()
{
hide();
}
void QgsCustomizationDialog::on_actionSave_triggered( bool checked )
{
QSettings mySettings;
QString lastDir = mySettings.value( mLastDirSettingsName, "." ).toString();
QString fileName = QFileDialog::getSaveFileName(this,
tr( "Choose a customization INI file" ),
lastDir, tr( "Customization files (*.ini)" ) );
if ( fileName.isEmpty() ) return;
QFileInfo fileInfo( fileName );
mySettings.setValue ( mLastDirSettingsName, fileInfo.absoluteDir().absolutePath () );
QSettings fileSettings( fileName, QSettings::IniFormat);
treeToSettings ( &fileSettings );
}
void QgsCustomizationDialog::on_actionLoad_triggered( bool checked )
{
QSettings mySettings;
QString lastDir = mySettings.value( mLastDirSettingsName, "." ).toString();
QString fileName = QFileDialog::getOpenFileName(this,
tr( "Choose a customization INI file" ),
lastDir, tr( "Customization files (*.ini)" ) );
if ( fileName.isEmpty() ) return;
QFileInfo fileInfo( fileName );
mySettings.setValue ( mLastDirSettingsName, fileInfo.absoluteDir().absolutePath () );
QSettings fileSettings( fileName, QSettings::IniFormat);
settingsToTree ( &fileSettings );
}
void QgsCustomizationDialog::on_actionExpandAll_triggered( bool checked )
{
treeWidget->expandAll();
}
void QgsCustomizationDialog::on_actionCollapseAll_triggered( bool checked )
{
treeWidget->collapseAll();
}
void QgsCustomizationDialog::on_actionSelectAll_triggered( bool checked )
{
QList<QTreeWidgetItem*> items = treeWidget->findItems("*",Qt::MatchWildcard|Qt::MatchRecursive, 0);
QList<QTreeWidgetItem*>::iterator i;
for ( i = items.begin(); i != items.end(); ++i)
{
(*i)->setCheckState(0, Qt::Checked);
}
}
void QgsCustomizationDialog::init()
{
QgsDebugMsg( "Entered" );
QTreeWidgetItem * wi = createTreeItemWidgets();
if ( wi ) {
treeWidget->insertTopLevelItem(0, wi );
treeWidget->expandItem( wi );
}
treeWidget->insertTopLevelItems( 0, QgsCustomization::instance()->mMainWindowItems );
for (int i = 0; i < treeWidget->topLevelItemCount(); i++)
treeWidget->expandItem( treeWidget->topLevelItem(i) );
// load check states from the settings
reset();
treeWidget->sortItems(0, Qt::AscendingOrder);
treeWidget->resizeColumnToContents(0);
}
QTreeWidgetItem * QgsCustomizationDialog::createTreeItemWidgets()
{
QgsDebugMsg( "Entered" );
QDomDocument myDoc( "QgsWidgets" );
QFile myFile( QgsApplication::pkgDataPath() + "/resources/customization.xml" );
if( !myFile.open( QIODevice::ReadOnly ) )
{
return NULL;
}
if( !myDoc.setContent( &myFile ) )
{
myFile.close();
return NULL;
}
myFile.close();
QDomElement myRoot = myDoc.documentElement();
if( myRoot.tagName() != "qgiswidgets" )
{
return NULL;
}
QTreeWidgetItem *myItem = readWidgetsXmlNode ( myRoot );
myItem->setData ( 0, Qt::DisplayRole, tr("Widgets" ) );
return myItem;
}
QTreeWidgetItem * QgsCustomizationDialog::readWidgetsXmlNode ( QDomNode theNode )
{
QgsDebugMsg( "Entered" );
QDomElement myElement = theNode.toElement();
QString name = myElement.attribute( "objectName", "");
QStringList data( name );
data << myElement.attribute( "label", name);
data << myElement.attribute( "description", "");
QTreeWidgetItem *myItem = new QTreeWidgetItem ( data );
// It is nice to have icons for each Qt widget class, is it too heavy?
// There are 47 png files, total 196K in qt/tools/designer/src/components/formeditor/images/
QString iconName = myElement.attribute( "class", "" ).toLower().mid(1) + ".png";
QString iconPath = QgsApplication::iconPath( "/customization/" + iconName );
QgsDebugMsg( "iconPath = " + iconPath );
if ( QFile::exists( iconPath ) )
{
myItem->setIcon (0, QIcon(iconPath) );
}
myItem->setFlags ( Qt::ItemIsEnabled | Qt::ItemIsUserCheckable | Qt::ItemIsSelectable );
myItem->setCheckState(0, Qt::Checked);
QDomNode n = theNode.firstChild();
while( !n.isNull() )
{
QDomElement e = n.toElement();
if( !e.isNull() )
{
QTreeWidgetItem *wi = readWidgetsXmlNode ( n );
myItem->insertChild ( 0, wi );
}
n = n.nextSibling();
}
return myItem;
}
bool QgsCustomizationDialog::switchWidget ( QWidget * widget, QMouseEvent *event )
{
QgsDebugMsg ( "Entered" );
if ( !actionCatch->isChecked() ) { return false; }
QString path = widgetPath(widget);
QgsDebugMsg ( "path = " + path );
if ( path.startsWith ( "/QgsCustomizationDialogBase" ) )
{
// do not allow modification of this dialog
return false;
}
else if ( path.startsWith( "/QgisApp" ) )
{
// changes to main window
// (work with toolbars, tool buttons)
if (widget->inherits("QToolBar"))
{
path = "/Toolbars/" + widget->objectName();
}
else if (widget->inherits("QToolButton"))
{
QToolButton* toolbutton = qobject_cast<QToolButton*>(widget);
QAction* action = toolbutton->defaultAction();
QString toolbarName = widget->parent()->objectName();
QString actionName = action->objectName();
path = "/Toolbars/" + toolbarName + "/" + actionName;
}
else
{
// unsupported widget in main window
return false;
}
}
else
{
// ordinary widget in a dialog
path = "/Widgets" + path;
}
QgsDebugMsg ( "path final = " + path );
bool on = !itemChecked ( path );
QgsDebugMsg ( QString ( "on = %1" ).arg(on) );
setItemChecked ( path, on );
QTreeWidgetItem *myItem = item ( path );
if ( myItem ) {
treeWidget->scrollToItem ( myItem, QAbstractItemView::PositionAtCenter );
treeWidget->clearSelection();
myItem->setSelected ( true );
QString style;
if ( !on ) {
style = "background-color: #FFCCCC;";
}
widget->setStyleSheet( style );
}
return true;
}
QString QgsCustomizationDialog::widgetPath ( QWidget * theWidget, QString thePath )
{
// go up until QDialog is reached
QString name = theWidget->objectName();
QString path = thePath;
if ( !QgsCustomization::mInternalWidgets.contains ( name ) )
{
if ( !path.isEmpty() ) {
path = name + "/" + path;
}
else
{
path = name;
}
}
QWidget * parent = theWidget->parentWidget();
if ( !parent || theWidget->inherits("QDialog") )
{
return "/" + path;
}
return widgetPath ( parent, path );
}
void QgsCustomizationDialog::setCatch ( bool on )
{
actionCatch->setChecked ( on );
}
bool QgsCustomizationDialog::catchOn ( )
{
return actionCatch->isChecked ( );
}
void QgsCustomization::addTreeItemActions(QTreeWidgetItem* parentItem, const QList<QAction*>& actions)
{
foreach (QAction* action, actions)
{
if (action->menu())
{
// it is a submenu
addTreeItemMenu(parentItem, action->menu());
}
else
{
// it is an ordinary action
QStringList strs;
strs << action->objectName() << action->text();
QTreeWidgetItem* myItem = new QTreeWidgetItem(parentItem, strs);
myItem->setIcon( 0, action->icon() );
myItem->setFlags ( Qt::ItemIsEnabled | Qt::ItemIsUserCheckable | Qt::ItemIsSelectable );
myItem->setCheckState(0, Qt::Checked);
}
}
}
void QgsCustomization::addTreeItemMenu(QTreeWidgetItem* parentItem, QMenu* menu)
{
QStringList menustrs;
menustrs << menu->objectName() << menu->title();
QTreeWidgetItem* menuItem = new QTreeWidgetItem( parentItem, menustrs);
menuItem->setFlags ( Qt::ItemIsEnabled | Qt::ItemIsUserCheckable | Qt::ItemIsSelectable );
menuItem->setCheckState(0, Qt::Checked);
addTreeItemActions(menuItem, menu->actions());
}
void QgsCustomization::createTreeItemMenus ( )
{
QStringList data;
data << "Menus";
QTreeWidgetItem *topItem = new QTreeWidgetItem ( data );
QMenuBar* menubar = QgisApp::instance()->menuBar();
foreach (QObject* obj, menubar->children())
{
if (obj->inherits("QMenu"))
{
QMenu* menu = qobject_cast<QMenu*>(obj);
addTreeItemMenu(topItem, menu);
}
}
mMainWindowItems << topItem;
}
void QgsCustomization::createTreeItemToolbars ( )
{
QStringList data;
data << "Toolbars";
QTreeWidgetItem *topItem = new QTreeWidgetItem ( data );
QMainWindow* mw = QgisApp::instance();
foreach (QObject* obj, mw->children())
{
if (obj->inherits("QToolBar"))
{
QToolBar* tb = qobject_cast<QToolBar*>(obj);
QStringList tbstrs;
tbstrs << tb->objectName() << tb->windowTitle();
QTreeWidgetItem* tbItem = new QTreeWidgetItem( topItem, tbstrs );
tbItem->setFlags ( Qt::ItemIsEnabled | Qt::ItemIsUserCheckable | Qt::ItemIsSelectable );
tbItem->setCheckState(0, Qt::Checked);
addTreeItemActions(tbItem, tb->actions());
}
}
mMainWindowItems << topItem;
}
void QgsCustomization::createTreeItemDocks ( )
{
QStringList data;
data << "Docks";
QTreeWidgetItem *topItem = new QTreeWidgetItem ( data );
QMainWindow* mw = QgisApp::instance();
foreach (QObject* obj, mw->children())
{
if (obj->inherits("QDockWidget"))
{
QDockWidget* dw = qobject_cast<QDockWidget*> (obj);
QStringList dwstrs;
dwstrs << dw->objectName() << dw->windowTitle();
QTreeWidgetItem* dwItem = new QTreeWidgetItem( topItem, dwstrs );
dwItem->setFlags ( Qt::ItemIsEnabled | Qt::ItemIsUserCheckable | Qt::ItemIsSelectable );
dwItem->setCheckState(0, Qt::Checked);
}
}
mMainWindowItems << topItem;
}
void QgsCustomization::createTreeItemStatus ( )
{
QStringList data;
data << "StatusBar";
QTreeWidgetItem *topItem = new QTreeWidgetItem ( data );
topItem->setFlags ( Qt::ItemIsEnabled | Qt::ItemIsUserCheckable | Qt::ItemIsSelectable );
topItem->setCheckState(0, Qt::Checked);
QStatusBar* sb = QgisApp::instance()->statusBar();
foreach (QObject* obj, sb->children())
{
if (obj->inherits("QWidget") && !obj->objectName().isEmpty())
{
QStringList strs;
strs << obj->objectName();
QTreeWidgetItem* item = new QTreeWidgetItem( topItem, strs );
item->setFlags ( Qt::ItemIsEnabled | Qt::ItemIsUserCheckable | Qt::ItemIsSelectable );
item->setCheckState(0, Qt::Checked);
}
}
mMainWindowItems << topItem;
}
QStringList QgsCustomization::mInternalWidgets = QStringList() << "qt_tabwidget_stackedwidget" << "qt_tabwidget_tabbar";
QgsCustomization *QgsCustomization::pinstance = 0;
QgsCustomization *QgsCustomization::instance()
{
if ( pinstance == 0 )
{
pinstance = new QgsCustomization();
}
return pinstance;
}
QgsCustomization::QgsCustomization( ) :
pDialog(0),
mEnabled(true),
mStatusPath("/Customization/status"),
mSettings ( "QuantumGIS", "QGISCUSTOMIZATION" )
{
QgsDebugMsg( "Entered" );
}
QgsCustomization::~QgsCustomization()
{
}
void QgsCustomization::updateMainWindow()
{
// collect tree items even if the customization is disabled
createTreeItemMenus();
createTreeItemToolbars();
createTreeItemDocks();
createTreeItemStatus();
if (!mEnabled)
return;
QMainWindow* mw = QgisApp::instance();
QMenuBar* menubar = mw->menuBar();
mSettings.beginGroup("Customization/Menus");
// hide menus and menu actions
foreach (QObject* obj, menubar->children())
{
if (obj->inherits("QMenu"))
{
QMenu* menu = qobject_cast<QMenu*>(obj);
bool visible = mSettings.value(menu->objectName(), true).toBool();
if (!visible)
{
menubar->removeAction(menu->menuAction());
}
else
{
updateMenu(menu, mSettings);
}
}
}
mSettings.endGroup();
// remove toolbars, toolbar actions
mSettings.beginGroup("Customization/Toolbars");
foreach (QObject* obj, mw->children())
{
if (obj->inherits("QToolBar"))
{
QToolBar* tb = qobject_cast<QToolBar*>(obj);
bool visible = mSettings.value(tb->objectName(), true).toBool();
if (!visible)
{
mw->removeToolBar(tb);
}
else
{
mSettings.beginGroup(tb->objectName());
// hide individual toolbar actions
foreach (QAction* action, tb->actions())
{
visible = mSettings.value(action->objectName(), true).toBool();
if (!visible)
tb->removeAction(action);
}
mSettings.endGroup();
}
}
}
mSettings.endGroup();
// remove dock widgets
mSettings.beginGroup("Customization/Docks");
foreach (QObject* obj, mw->children())
{
if (obj->inherits("QDockWidget"))
{
bool visible = mSettings.value(obj->objectName(), true).toBool();
if (!visible)
{
mw->removeDockWidget(qobject_cast<QDockWidget*>(obj));
}
}
}
mSettings.endGroup();
// remove status bar widgets
if (mSettings.value("Customization/StatusBar", true).toBool())
{
mSettings.beginGroup("Customization/StatusBar");
QStatusBar* sb = mw->statusBar();
foreach (QObject* obj, sb->children())
{
if (obj->inherits("QWidget"))
{
QWidget* widget = qobject_cast<QWidget*>(obj);
bool visible = mSettings.value(widget->objectName(), true).toBool();
if (!visible)
{
sb->removeWidget(widget);
}
}
}
mSettings.endGroup();
}
else
{
mw->statusBar()->hide();
//mw->setStatusBar( 0 ); // do not delete the status bar: some parts of the app use it
}
}
void QgsCustomization::updateMenu(QMenu* menu, QSettings& settings)
{
settings.beginGroup(menu->objectName());
// hide individual menu actions and call recursively on visible submenus
foreach (QAction* action, menu->actions())
{
QString objName = (action->menu() ? action->menu()->objectName() : action->objectName());
bool visible = settings.value(objName, true).toBool();
if (!visible)
menu->removeAction(action);
else if (action->menu())
{
// it is a submenu - let's look if there isn't something to remove
updateMenu(action->menu(), settings);
}
}
settings.endGroup();
}
void QgsCustomization::openDialog()
{
QgsDebugMsg( "Entered" );
if ( !pDialog ) {
pDialog = new QgsCustomizationDialog();
}
// I am trying too enable switching widget status by clicking in main app, so I need non modal
pDialog->show();
}
void QgsCustomization::customizeWidget( QWidget * widget, QEvent * event )
{
// Test if the widget is child of QDialog
if ( !widget->inherits("QDialog") ) return;
QgsDebugMsg( QString ( "objectName = %1 event type = %2" ).arg( widget->objectName()).arg( event->type() ) );
QgsDebugMsg( QString ( "%1 x %2").arg(typeid( *widget ).name()).arg(typeid( QDialog ).name() ));
QString path = "/Customization/Widgets/";
QgsCustomization::customizeWidget( path, widget );
}
void QgsCustomization::customizeWidget( QString thePath, QWidget * theWidget )
{
QSettings mySettings ("QuantumGIS", "QGISCUSTOMIZATION" );
QString name = theWidget->objectName();
QString myPath = thePath;
// Qt may insert some internal classes in the tree, e.g. QTabWidgetPrivate inserts
// qt_tabwidget_stackedwidget, such widgets do not appear in the tree generated
// from ui files and do not have sense from user poin of view -> skip
if ( !QgsCustomization::mInternalWidgets.contains ( name ) )
{
myPath = thePath + "/" + name;
}
QObjectList children = theWidget->children();
QObjectList::iterator i;
for ( i = children.begin(); i != children.end(); ++i)
{
if ( !(*i)->inherits("QWidget") ) continue;
QWidget * w = qobject_cast<QWidget*>(*i);
QString p = myPath + "/" + w->objectName();
bool on = mySettings.value( p, true ).toBool();
QgsDebugMsg( QString("p = %1 on = %2").arg(p).arg(on) );
if ( on )
{
QgsCustomization::customizeWidget( myPath, w );
}
else
{
QLayout *l = theWidget->layout();
if ( l )
{
QgsDebugMsg( "remove" );
QgsCustomization::removeFromLayout( l, w );
w->hide();
}
else
{
QgsDebugMsg( "hide" );
w->hide();
}
}
}
}
void QgsCustomization::removeFromLayout( QLayout *theLayout, QWidget * theWidget )
{
if ( theLayout->indexOf( theWidget ) >= 0 )
{
theLayout->removeWidget ( theWidget );
return;
}
else
{
QObjectList children = theLayout->children();
QObjectList::iterator i;
for ( i = children.begin(); i != children.end(); ++i)
{
if ( !(*i)->inherits("QLayout") ) continue;
QLayout *l = qobject_cast<QLayout*>(*i);
QgsCustomization::removeFromLayout( l, theWidget );
}
}
}
void QgsCustomization::preNotify( QObject * receiver, QEvent * event, bool * done )
{
QWidget * widget = 0;
if ( receiver->isWidgetType() )
{
widget = static_cast<QWidget*>( receiver );
}
if ( mEnabled && widget && event->type() == QEvent::Show )
{
QgsCustomization::customizeWidget ( widget, event );
if ( widget->inherits("QDialog") && pDialog && pDialog->isVisible() ) {
}
}
else if ( mEnabled && widget && (event->type() == QEvent::Hide || event->type() == QEvent::Close) )
{
if ( widget->inherits("QDialog") && pDialog && pDialog->isVisible() ){
}
}
else if ( widget && event->type() == QEvent::MouseButtonPress )
{
QgsDebugMsg( "click" );
if ( pDialog && pDialog->isVisible() ) {
QMouseEvent *e = static_cast<QMouseEvent*>(event);
*done = pDialog->switchWidget ( widget, e );
}
}
// Shortcut arrives only if it is defined and used in main app
// This would be also possible without necessity to add shortcut to main app
// but it is better to have it there to avoid future conflicts
else if ( event->type() == QEvent::KeyPress )
{
if ( pDialog && pDialog->isVisible() ) {
QKeyEvent *e = static_cast<QKeyEvent*>(event);
QgsDebugMsg( QString("key = %1 modifiers = %2").arg(e->key()).arg(e->modifiers() ) ) ;
if ( e->key() == Qt::Key_M && e->modifiers() == Qt::ControlModifier )
{
pDialog->setCatch ( !pDialog->catchOn() );
}
}
}
}
void QgsCustomization::loadDefault()
{
QSettings mySettings;
// Check customization state
int status = mySettings.value( mStatusPath, QgsCustomization::NotSet).toInt();
QgsDebugMsg( "Status path = " + mStatusPath );
QgsDebugMsg( QString("status = %1").arg(status) );
if ( status == QgsCustomization::User || status == QgsCustomization::Default ) return;
// Look for default
QString path = QgsApplication::pkgDataPath() + "/resources/customization.ini";
if ( ! QFile::exists( path ) )
{
QgsDebugMsg( "Default customization not found in " + path );
return;
}
QgsDebugMsg( "Loading default customization from " + path );
QSettings fileSettings( path, QSettings::IniFormat);
QStringList keys = fileSettings.allKeys();
QgsDebugMsg( QString("size = %1").arg( keys.size () ) );
QStringList::const_iterator i;
for ( i = keys.begin(); i != keys.end(); ++i)
{
QString p(*i);
bool val = fileSettings.value(p).toBool();
mSettings.setValue(p, val);
}
mySettings.setValue(mStatusPath, QgsCustomization::Default);
}

165
src/app/qgscustomization.h Normal file
View File

@ -0,0 +1,165 @@
/***************************************************************************
qgscustomization.h - Customization
-------------------
begin : 2011-04-01
copyright : (C) 2011 Radim Blazek
email : radim dot blazek at gmail 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. *
* *
***************************************************************************/
/* $Id$ */
#ifndef QGSCUSTOMIZATION_H
#define QGSCUSTOMIZATION_H
#include "ui_qgscustomizationdialogbase.h"
#include <QDialog>
#include <QDomNode>
#include <QEvent>
#include <QMouseEvent>
#include <QSettings>
#include <QTreeWidgetItem>
class QString;
class QWidget;
class QTreeWidgetItem;
class QgsCustomizationDialog : public QMainWindow, private Ui::QgsCustomizationDialogBase
{
Q_OBJECT
public:
QgsCustomizationDialog();
~QgsCustomizationDialog();
// get item by path
QTreeWidgetItem *item ( QString thePath, QTreeWidgetItem *theItem=0 );
//
// return current item state for given path
bool itemChecked ( QString thePath );
// set item state for given path
void setItemChecked ( QString thePath, bool on );
// recursively save tree item to settings
void itemToSettings( QString thePath, QTreeWidgetItem *theItem, QSettings *theSettings );
// recursively save settings to tree items
void settingsToItem( QString thePath, QTreeWidgetItem *theItem, QSettings *theSettings );
// save current tree to settings
void treeToSettings ( QSettings *theSettings );
// restore current tree from settings
void settingsToTree ( QSettings *theSettings );
// switch widget item in tree
bool switchWidget ( QWidget * widget, QMouseEvent *event );
// Get path of the widget
QString widgetPath ( QWidget * theWidget, QString thePath = QString() );
void setCatch ( bool on );
bool catchOn ( );
private slots:
//void on_btnQgisUser_clicked();
// Save to settings
void ok();
void apply();
void cancel();
// Reset values from settings
void reset();
// Save to settings to file
void on_actionSave_triggered( bool checked );
// Load settings from file
void on_actionLoad_triggered( bool checked );
void on_actionExpandAll_triggered( bool checked );
void on_actionCollapseAll_triggered( bool checked );
void on_actionSelectAll_triggered( bool checked );
private:
void init();
QTreeWidgetItem * createTreeItemWidgets ( );
QTreeWidgetItem * readWidgetsXmlNode ( QDomNode theNode );
QString mLastDirSettingsName;
QSettings mSettings;
};
class QgsCustomization : public QObject
{
Q_OBJECT
public:
enum Status
{
NotSet = 0,
User = 1, // Set by user
Default = 2 // Default customization loaded and set
};
//! Returns the instance pointer, creating the object on the first call
static QgsCustomization* instance();
void openDialog();
static void customizeWidget( QWidget * widget, QEvent * event );
static void customizeWidget( QString path, QWidget * widget );
static void removeFromLayout( QLayout *theLayout, QWidget * widget );
void updateMainWindow();
// make sure to enable/disable before creating QgisApp in order to get it customized (or not)
void setEnabled(bool enabled) { mEnabled = enabled; }
bool isEnabled() const { return mEnabled; }
// Load and set default customization
void loadDefault();
// Internal Qt widget which has to bes kipped in paths
static QStringList mInternalWidgets;
QString statusPath() { return mStatusPath; }
public slots:
void preNotify( QObject * receiver, QEvent * event, bool * done );
protected:
QgsCustomization( );
~QgsCustomization();
QgsCustomizationDialog *pDialog;
bool mEnabled;
QString mStatusPath;
void updateMenu(QMenu* menu, QSettings& settings);
void createTreeItemMenus ( );
void createTreeItemToolbars ( );
void createTreeItemDocks ( );
void createTreeItemStatus ( );
void addTreeItemMenu(QTreeWidgetItem* parentItem, QMenu* menu);
void addTreeItemActions(QTreeWidgetItem* parentItem, const QList<QAction*>& actions);
QList<QTreeWidgetItem*> mMainWindowItems;
friend class QgsCustomizationDialog; // in order to access mMainWindowItems
private slots:
private:
static QgsCustomization* pinstance;
QSettings mSettings;
};
#endif // QGSCUSTOMIZATION_H

View File

@ -215,7 +215,7 @@ void QgsVectorLayerProperties::setRow( int row, int idx, const QgsField &field )
QPushButton *pb = new QPushButton( editTypeButtonText( layer->editType( idx ) ) );
tblAttributes->setCellWidget( row, attrEditTypeCol, pb );
connect( pb, SIGNAL( clicked() ), this, SLOT( attributeTypeDialog() ) );
connect( pb, SIGNAL( pressed() ), this, SLOT( attributeTypeDialog( ) ) );
mButtonMap.insert( idx, pb );
//set the alias for the attribute
@ -231,7 +231,7 @@ QgsVectorLayerProperties::~QgsVectorLayerProperties()
settings.setValue( "/Windows/VectorLayerProperties/row", tabWidget->currentIndex() );
}
void QgsVectorLayerProperties::attributeTypeDialog()
void QgsVectorLayerProperties::attributeTypeDialog( )
{
QPushButton *pb = qobject_cast<QPushButton *>( sender() );
if ( !pb )
@ -271,7 +271,6 @@ void QgsVectorLayerProperties::attributeTypeDialog()
break;
case QgsVectorLayer::CheckBox:
mCheckedStates.insert( index, attributeTypeDialog.checkedState() );
break;
case QgsVectorLayer::LineEdit:
case QgsVectorLayer::TextEdit:
case QgsVectorLayer::UniqueValues:
@ -384,22 +383,20 @@ void QgsVectorLayerProperties::editingToggled()
void QgsVectorLayerProperties::updateButtons()
{
int cap = layer->dataProvider()->capabilities();
mToggleEditingButton->setEnabled(( cap & QgsVectorDataProvider::EditingCapabilities ) && !layer->isReadOnly() );
mToggleEditingButton->setChecked( layer->isEditable() );
if ( layer->isEditable() )
{
int cap = layer->dataProvider()->capabilities();
mAddAttributeButton->setEnabled( cap & QgsVectorDataProvider::AddAttributes );
mDeleteAttributeButton->setEnabled( cap & QgsVectorDataProvider::DeleteAttributes );
mCalculateFieldButton->setEnabled( cap & QgsVectorDataProvider::ChangeAttributeValues );
mToggleEditingButton->setChecked( true );
}
else
{
mAddAttributeButton->setDisabled( true );
mDeleteAttributeButton->setDisabled( true );
mCalculateFieldButton->setDisabled( true );
mAddAttributeButton->setEnabled( false );
mDeleteAttributeButton->setEnabled( false );
mToggleEditingButton->setChecked( false );
mCalculateFieldButton->setEnabled( false );
}
}
@ -608,44 +605,30 @@ void QgsVectorLayerProperties::apply()
QgsVectorLayer::EditType editType = editTypeFromButtonText( pb->text() );
layer->setEditType( idx, editType );
switch ( editType )
if ( editType == QgsVectorLayer::ValueMap )
{
case QgsVectorLayer::ValueMap:
if ( mValueMaps.contains( idx ) )
{
QMap<QString, QVariant> &map = layer->valueMap( idx );
map.clear();
map = mValueMaps[idx];
}
break;
case QgsVectorLayer::EditRange:
case QgsVectorLayer::SliderRange:
case QgsVectorLayer::DialRange:
if ( mRanges.contains( idx ) )
{
layer->range( idx ) = mRanges[idx];
}
break;
case QgsVectorLayer::CheckBox:
if ( mCheckedStates.contains( idx ) )
{
layer->setCheckedState( idx, mCheckedStates[idx].first, mCheckedStates[idx].second );
}
break;
case QgsVectorLayer::LineEdit:
case QgsVectorLayer::UniqueValues:
case QgsVectorLayer::UniqueValuesEditable:
case QgsVectorLayer::Classification:
case QgsVectorLayer::FileName:
case QgsVectorLayer::Enumeration:
case QgsVectorLayer::Immutable:
case QgsVectorLayer::Hidden:
case QgsVectorLayer::TextEdit:
case QgsVectorLayer::Calendar:
break;
if ( mValueMaps.contains( idx ) )
{
QMap<QString, QVariant> &map = layer->valueMap( idx );
map.clear();
map = mValueMaps[idx];
}
}
else if ( editType == QgsVectorLayer::EditRange ||
editType == QgsVectorLayer::SliderRange ||
editType == QgsVectorLayer::DialRange )
{
if ( mRanges.contains( idx ) )
{
layer->range( idx ) = mRanges[idx];
}
}
else if ( editType == QgsVectorLayer::CheckBox )
{
if ( mCheckedStates.contains( idx ) )
{
layer->setCheckedState( idx, mCheckedStates[idx].first, mCheckedStates[idx].second );
}
}
}
@ -834,234 +817,7 @@ void QgsVectorLayerProperties::on_pbnIndex_clicked()
QString QgsVectorLayerProperties::metadata()
{
QString myMetadata = "<html><body>";
myMetadata += "<table width=\"100%\">";
//-------------
myMetadata += "<tr class=\"glossy\"><td>";
myMetadata += tr( "General:" );
myMetadata += "</td></tr>";
// data comment
if ( !( layer->dataComment().isEmpty() ) )
{
myMetadata += "<tr><td>";
myMetadata += tr( "Layer comment: %1" ).arg( layer->dataComment() );
myMetadata += "</td></tr>";
}
//storage type
myMetadata += "<tr><td>";
myMetadata += tr( "Storage type of this layer: %1" ).arg( layer->storageType() );
myMetadata += "</td></tr>";
// data source
myMetadata += "<tr><td>";
myMetadata += tr( "Source for this layer: %1" ).arg( layer->publicSource() );
myMetadata += "</td></tr>";
//geom type
QGis::GeometryType type = layer->geometryType();
if ( type < 0 || type > QGis::NoGeometry )
{
QgsDebugMsg( "Invalid vector type" );
}
else
{
QString typeString( QGis::qgisVectorGeometryType[layer->geometryType()] );
myMetadata += "<tr><td>";
myMetadata += tr( "Geometry type of the features in this layer: %1" ).arg( typeString );
myMetadata += "</td></tr>";
}
//feature count
myMetadata += "<tr><td>";
myMetadata += tr( "The number of features in this layer: %1" ).arg( layer->featureCount() );
myMetadata += "</td></tr>";
//capabilities
myMetadata += "<tr><td>";
myMetadata += tr( "Editing capabilities of this layer: %1" ).arg( layer->capabilitiesString() );
myMetadata += "</td></tr>";
//-------------
QgsRectangle myExtent = layer->extent();
myMetadata += "<tr class=\"glossy\"><td>";
myMetadata += tr( "Extents:" );
myMetadata += "</td></tr>";
//extents in layer cs TODO...maybe make a little nested table to improve layout...
myMetadata += "<tr><td>";
// Try to be a bit clever over what number format we use for the
// extents. Some people don't like it using scientific notation when the
// numbers get large, but for small numbers this is the more practical
// option (so we can't force the format to 'f' for all values).
// The scheme:
// - for all numbers with more than 5 digits, force non-scientific notation
// and 2 digits after the decimal point.
// - for all smaller numbers let the OS decide which format to use (it will
// generally use non-scientific unless the number gets much less than 1).
QString xMin, yMin, xMax, yMax;
double changeoverValue = 99999; // The 'largest' 5 digit number
if ( qAbs( myExtent.xMinimum() ) > changeoverValue )
{
xMin = QString( "%1" ).arg( myExtent.xMinimum(), 0, 'f', 2 );
}
else
{
xMin = QString( "%1" ).arg( myExtent.xMinimum() );
}
if ( qAbs( myExtent.yMinimum() ) > changeoverValue )
{
yMin = QString( "%1" ).arg( myExtent.yMinimum(), 0, 'f', 2 );
}
else
{
yMin = QString( "%1" ).arg( myExtent.yMinimum() );
}
if ( qAbs( myExtent.xMaximum() ) > changeoverValue )
{
xMax = QString( "%1" ).arg( myExtent.xMaximum(), 0, 'f', 2 );
}
else
{
xMax = QString( "%1" ).arg( myExtent.xMaximum() );
}
if ( qAbs( myExtent.yMaximum() ) > changeoverValue )
{
yMax = QString( "%1" ).arg( myExtent.yMaximum(), 0, 'f', 2 );
}
else
{
yMax = QString( "%1" ).arg( myExtent.yMaximum() );
}
myMetadata += tr( "In layer spatial reference system units : " )
+ tr( "xMin,yMin %1,%2 : xMax,yMax %3,%4" )
.arg( xMin ).arg( yMin ).arg( xMax ).arg( yMax );
myMetadata += "</td></tr>";
//extents in project cs
try
{
#if 0
// TODO: currently disabled, will revisit later [MD]
QgsRectangle myProjectedExtent = coordinateTransform->transformBoundingBox( layer->extent() );
myMetadata += "<tr><td>";
myMetadata += tr( "In project spatial reference system units : " )
+ tr( "xMin,yMin %1,%2 : xMax,yMax %3,%4" )
.arg( myProjectedExtent.xMinimum() )
.arg( myProjectedExtent.yMinimum() )
.arg( myProjectedExtent.xMaximum() )
.arg( myProjectedExtent.yMaximum() );
myMetadata += "</td></tr>";
#endif
//
// Display layer spatial ref system
//
myMetadata += "<tr class=\"glossy\"><td>";
myMetadata += tr( "Layer Spatial Reference System:" );
myMetadata += "</td></tr>";
myMetadata += "<tr><td>";
myMetadata += layer->crs().toProj4().replace( QRegExp( "\"" ), " \"" );
myMetadata += "</td></tr>";
//
// Display project (output) spatial ref system
//
#if 0
// TODO: disabled for now, will revisit later [MD]
myMetadata += "<tr><td bgcolor=\"gray\">";
myMetadata += tr( "Project (Output) Spatial Reference System:" );
myMetadata += "</td></tr>";
myMetadata += "<tr><td>";
myMetadata += coordinateTransform->destCRS().toProj4().replace( QRegExp( "\"" ), " \"" );
myMetadata += "</td></tr>";
#endif
}
catch ( QgsCsException &cse )
{
Q_UNUSED( cse );
QgsDebugMsg( cse.what() );
myMetadata += "<tr><td>";
myMetadata += tr( "In project spatial reference system units : " )
+ tr( "(Invalid transformation of layer extents)" );
myMetadata += "</td></tr>";
}
#if 0
//
// Add the info about each field in the attribute table
//
myMetadata += "<tr class=\"glossy\"><td>";
myMetadata += tr( "Attribute field info:" );
myMetadata += "</td></tr>";
myMetadata += "<tr><td>";
// Start a nested table in this trow
myMetadata += "<table width=\"100%\">";
myMetadata += "<tr><th>";
myMetadata += tr( "Field" );
myMetadata += "</th>";
myMetadata += "<th>";
myMetadata += tr( "Type" );
myMetadata += "</th>";
myMetadata += "<th>";
myMetadata += tr( "Length" );
myMetadata += "</th>";
myMetadata += "<th>";
myMetadata += tr( "Precision" );
myMetadata += "</th>";
myMetadata += "<th>";
myMetadata += tr( "Comment" );
myMetadata += "</th>";
//get info for each field by looping through them
const QgsFieldMap& myFields = layer->pendingFields();
for ( QgsFieldMap::const_iterator it = myFields.begin(); it != myFields.end(); ++it )
{
const QgsField& myField = *it;
myMetadata += "<tr><td>";
myMetadata += myField.name();
myMetadata += "</td>";
myMetadata += "<td>";
myMetadata += myField.typeName();
myMetadata += "</td>";
myMetadata += "<td>";
myMetadata += QString( "%1" ).arg( myField.length() );
myMetadata += "</td>";
myMetadata += "<td>";
myMetadata += QString( "%1" ).arg( myField.precision() );
myMetadata += "</td>";
myMetadata += "<td>";
myMetadata += QString( "%1" ).arg( myField.comment() );
myMetadata += "</td></tr>";
}
//close field list
myMetadata += "</table>"; //end of nested table
#endif
myMetadata += "</td></tr>"; //end of stats container table row
//
// Close the table
//
myMetadata += "</table>";
myMetadata += "</body></html>";
return myMetadata;
return layer->metadata();
}

112
src/browser/CMakeLists.txt Normal file
View File

@ -0,0 +1,112 @@
########################################################
# Files
SET (BROWSER_SRCS
main.cpp
qgsbrowser.cpp
qgsbrowsermodel.cpp
)
SET (BROWSER_UIS qgsbrowserbase.ui)
SET (BROWSER_MOC_HDRS
qgsbrowser.h
qgsbrowsermodel.h
)
#SET (BROWSER_RCCS qgsgps_plugin.qrc)
IF (WIN32)
IF (MSVC)
SET (BROWSER_SRCS ${BROWSER_SRCS} ${CMAKE_CURRENT_SOURCE_DIR}/../app/qgis_win32.rc)
ELSE(MSVC)
# Icon for windows MINGW
# Note: can't include .rc directly to source files
# as it's ignored when used MinGW
IF (NOT WINDRES)
FIND_PROGRAM(WINDRES windres)
IF (NOT WINDRES)
MESSAGE(FATAL_ERROR "windres not found - aborting")
ENDIF (NOT WINDRES)
ENDIF (NOT WINDRES)
#############################################################
# application icon
# resource compilation for MinGW
ADD_CUSTOM_COMMAND( OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/icon.o
COMMAND ${WINDRES} -I${CMAKE_CURRENT_SOURCE_DIR} -i${CMAKE_CURRENT_SOURCE_DIR}/../app/qgis_win32.rc
-o ${CMAKE_CURRENT_BINARY_DIR}/icon.o )
SET(QGIS_APP_SRCS ${QGIS_APP_SRCS} ${CMAKE_CURRENT_BINARY_DIR}/icon.o)
ENDIF (MSVC)
ENDIF (WIN32)
SET(IMAGE_RCCS ../../images/images.qrc)
########################################################
# Build
QT4_WRAP_UI (BROWSER_UIS_H ${BROWSER_UIS})
QT4_WRAP_CPP (BROWSER_MOC_SRCS ${BROWSER_MOC_HDRS})
QT4_ADD_RESOURCES(IMAGE_RCC_SRCS ${IMAGE_RCCS})
#QT4_ADD_RESOURCES(BROWSER_RCC_SRCS ${BROWSER_RCCS})
ADD_EXECUTABLE (qbrowser MACOSX_BUNDLE ${BROWSER_SRCS} ${BROWSER_MOC_SRCS} ${BROWSER_UIS_H} ${IMAGE_RCC_SRCS})
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/../core
${CMAKE_CURRENT_SOURCE_DIR}/../core/raster
${CMAKE_CURRENT_SOURCE_DIR}/../gui
${CMAKE_CURRENT_SOURCE_DIR}/../gui/attributetable
${CMAKE_CURRENT_BINARY_DIR}/../ui
${CMAKE_CURRENT_BINARY_DIR}
${GDAL_INCLUDE_DIR} # remove once raster layer is cleaned up
)
IF (WITH_INTERNAL_SPATIALITE)
INCLUDE_DIRECTORIES(../core/spatialite/headers/spatialite)
ELSE (WITH_INTERNAL_SPATIALITE)
INCLUDE_DIRECTORIES(${SQLITE3_INCLUDE_DIR})
ENDIF (WITH_INTERNAL_SPATIALITE)
TARGET_LINK_LIBRARIES(qbrowser qgis_core qgis_gui)
IF (NOT WITH_INTERNAL_SPATIALITE)
TARGET_LINK_LIBRARIES(qbrowser ${SQLITE3_LIBRARY})
ENDIF (NOT WITH_INTERNAL_SPATIALITE)
IF (${QTVERSION} STRLESS "4.3.0")
TARGET_LINK_LIBRARIES(qbrowser
${QT_LIBRARIES}
)
ELSE (${QTVERSION} STRLESS "4.3.0")
TARGET_LINK_LIBRARIES(qbrowser
${QT_QTCORE_LIBRARY}
${QT_QTGUI_LIBRARY}
${QT_QTNETWORK_LIBRARY}
${QT_QTSVG_LIBRARY}
${QT_QTXML_LIBRARY}
${QT_QTWEBKIT_LIBRARY}
)
ENDIF (${QTVERSION} STRLESS "4.3.0")
SET_TARGET_PROPERTIES(qbrowser PROPERTIES
INSTALL_RPATH ${CMAKE_INSTALL_PREFIX}/${QGIS_LIB_DIR}
INSTALL_RPATH_USE_LINK_PATH true
)
########################################################
# Install
IF (APPLE)
INSTALL (TARGETS qbrowser BUNDLE DESTINATION ${QGIS_BIN_DIR})
# needed because global install_name prefix is for main qgis app
INSTALL (CODE "EXECUTE_PROCESS(COMMAND install_name_tool -change ${CMAKE_INSTALL_NAME_DIR}/libqgis_core.${COMPLETE_VERSION}.dylib @executable_path/../../../../lib/libqgis_core.${COMPLETE_VERSION}.dylib \"$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/${QGIS_BIN_DIR}/qbrowser.app/Contents/MacOS/qbrowser\")")
INSTALL (CODE "EXECUTE_PROCESS (COMMAND ln -sfh ../../../${QGIS_FW_SUBDIR} \"$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/${QGIS_BIN_DIR}/qbrowser.app/Contents/Frameworks\")")
ELSE (APPLE)
INSTALL (TARGETS qbrowser RUNTIME DESTINATION ${QGIS_BIN_DIR})
ENDIF (APPLE)

112
src/browser/main.cpp Normal file
View File

@ -0,0 +1,112 @@
/***************************************************************************
main.cpp
Browser main method
-------------------
begin : 2011-04-01
copyright : (C) 2011 Radim Blazek
email : radim dot blazek at gmail 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 <iostream>
#include <QLocale>
#include <QSettings>
#include <QTranslator>
#include <QMainWindow>
#include <QLabel>
#include <QDialog>
#include <QApplication>
#include "qgsbrowser.h"
#include "qgsapplication.h"
#include "qgslogger.h"
#include "qgsconfig.h"
#include <qmainwindow.h>
int main( int argc, char ** argv )
{
QSettings settings;
QgsApplication a( argc, argv, true );
a.setThemeName( settings.value( "/Themes", "default" ).toString() );
// load providers
#if defined(Q_WS_WIN)
QString prefixPath = QApplication::applicationDirPath();
#else
QString prefixPath = QApplication::applicationDirPath()+"/..";
#endif
a.setPrefixPath( prefixPath, true );
a.initQgis();
// Set up the QSettings environment must be done after qapp is created
QCoreApplication::setOrganizationName( "QuantumGIS" );
QCoreApplication::setOrganizationDomain( "qgis.org" );
QCoreApplication::setApplicationName( "QGIS" );
/*
QString myTranslationCode = "";
// This is mostly copy from Help viewer - not sure if important
#if defined(Q_WS_MACX)
// If we're on Mac, we have the resource library way above us...
a.setPkgDataPath( QgsApplication::prefixPath() + "/../../../../" + QString( QGIS_DATA_SUBDIR ) );
#elif defined(Q_WS_WIN)
a.setPkgDataPath( QgsApplication::prefixPath() + "/" QGIS_DATA_SUBDIR );
#else
a.setPkgDataPath( QgsApplication::prefixPath() + "/../" QGIS_DATA_SUBDIR );
#endif
QString i18nPath = QgsApplication::i18nPath();
if ( myTranslationCode.isEmpty() )
{
myTranslationCode = QLocale::system().name();
QSettings settings;
if ( settings.value( "locale/overrideFlag", false ).toBool() )
{
myTranslationCode = settings.value( "locale/userLocale", "en_US" ).toString();
}
}
QgsDebugMsg( QString( "Setting translation to %1/qgis_%2" ).arg( i18nPath ).arg( myTranslationCode ) );
*/
/* Translation file for Qt.
* The strings from the QMenuBar context section are used by Qt/Mac to shift
* the About, Preferences and Quit items to the Mac Application menu.
* These items must be translated identically in both qt_ and qgis_ files.
*/
/*
QTranslator qttor( 0 );
if ( qttor.load( QString( "qt_" ) + myTranslationCode, i18nPath ) )
{
a.installTranslator( &qttor );
}
*/
/* Translation file for QGIS.
*/
/*
QTranslator qgistor( 0 );
if ( qgistor.load( QString( "qgis_" ) + myTranslationCode, i18nPath ) )
{
a.installTranslator( &qgistor );
}
*/
QgsBrowser w;
a.connect( &a, SIGNAL( aboutToQuit() ), &w, SLOT( saveWindowState() ) );
w.restoreWindowState();
w.show();
a.connect( &a, SIGNAL( lastWindowClosed() ), &a, SLOT( quit() ) );
return a.exec();
}

481
src/browser/qgsbrowser.cpp Normal file
View File

@ -0,0 +1,481 @@
/***************************************************************************
qgs.cpp -
-------------------
begin : 2011-04-01
copyright : (C) 2011 Radim Blazek
email : radim dot blazek at gmail 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. *
* *
***************************************************************************/
/* $Id$ */
#include <typeinfo>
#include <QSettings>
#include <QMessageBox>
#include <QKeyEvent>
#include "qgsapplication.h"
#include "qgsdataitem.h"
#include "qgsbrowser.h"
#include "qgsbrowsermodel.h"
#include "qgsencodingfiledialog.h"
#include "qgsgenericprojectionselector.h"
#include "qgslogger.h"
#include "qgsmaplayerregistry.h"
#include "qgsproviderregistry.h"
#include "qgsvectorlayer.h"
#include "qgsrasterlayer.h"
#include "qgsnewvectorlayerdialog.h"
QgsBrowser::QgsBrowser( QWidget *parent, Qt::WFlags flags )
: QMainWindow( parent, flags ),
mDirtyMetadata( true ), mDirtyPreview( true ), mDirtyAttributes( true ),
mLayer( 0 ), mParamWidget(0)
{
setupUi( this );
// Disable tabs by default
tabWidget->setTabEnabled ( tabWidget->indexOf( paramTab ), false );
tabWidget->setTabEnabled ( tabWidget->indexOf( metaTab ), false );
tabWidget->setTabEnabled ( tabWidget->indexOf( previewTab ), false );
tabWidget->setTabEnabled ( tabWidget->indexOf( attributesTab ), false );
mModel = new QgsBrowserModel(treeView);
treeView->setModel(mModel);
// Last expanded is stored, dont cover whole height with file system
//treeView->expand( mModel->index(0,0) );
connect(treeView, SIGNAL(clicked(const QModelIndex&)), this, SLOT(itemClicked(const QModelIndex&)));
treeView->setExpandsOnDoubleClick (false);
connect(treeView, SIGNAL(doubleClicked(const QModelIndex&)), this, SLOT(itemDoubleClicked(const QModelIndex&)));
connect(treeView, SIGNAL(expanded(const QModelIndex&)), this, SLOT(itemExpanded(const QModelIndex&)));
connect(tabWidget, SIGNAL(currentChanged(int)), this, SLOT(tabChanged()));
connect( mActionNewVectorLayer, SIGNAL( triggered() ), this, SLOT( newVectorLayer() ) );
connect(stopRenderingButton, SIGNAL(clicked()), this, SLOT(stopRendering()) );
mapCanvas->setCanvasColor(Qt::white);
QSettings settings;
QString lastPath = settings.value ( "/Browser/lastExpanded" ).toString();
QgsDebugMsg ( "lastPath = " + lastPath );
if ( !lastPath.isEmpty() )
{
expand( lastPath );
}
}
QgsBrowser::~QgsBrowser()
{
}
void QgsBrowser::expand( QString path, const QModelIndex& index )
{
QStringList paths = path.split('/');
for ( int i = 0; i < mModel->rowCount(index); i++ )
{
QModelIndex idx = mModel->index(i, 0, index);
QgsDataItem* ptr = (QgsDataItem*) idx.internalPointer();
if ( path.indexOf ( ptr->mPath ) == 0 )
{
treeView->expand( idx );
treeView->scrollTo (idx, QAbstractItemView::PositionAtTop );
expand( path, idx );
break;
}
}
}
void QgsBrowser::itemClicked(const QModelIndex& index)
{
mIndex = index;
QgsDataItem* ptr = (QgsDataItem*) index.internalPointer();
// Disable preview, attributes tab
bool paramEnable = false;
bool metaEnable = false;
bool previewEnable = false;
bool attributesEnable = false;
// mark all tabs as dirty
mDirtyMetadata = true;
mDirtyPreview = true;
mDirtyAttributes = true;
// clear the previous stuff
attributeTable->setLayer( NULL );
QList<QgsMapCanvasLayer> nolayers;
mapCanvas->setLayerSet( nolayers );
metaTextBrowser->clear();
if ( mParamWidget ) {
paramLayout->removeWidget ( mParamWidget );
mParamWidget->hide();
delete mParamWidget;
mParamWidget = 0;
}
// QgsMapLayerRegistry deletes the previous layer(s) for us
// TODO: in future we could cache the layers in the registry
QgsMapLayerRegistry::instance()->removeAllMapLayers();
mLayer = 0;
// this should probably go to the model and only emit signal when a layer is clicked
mActionSetProjection->setEnabled ( ptr->capabilities() & QgsDataItem::SetCrs );
mParamWidget = ptr->paramWidget();
if ( mParamWidget ) {
paramLayout->addWidget ( mParamWidget );
mParamWidget->show();
paramEnable = true;
}
QgsMapLayer::LayerType type;
QString providerKey;
QString uri;
if ( ptr->layerInfo(type, providerKey, uri) )
{
QgsDebugMsg ( providerKey + " : " + uri );
if ( type == QgsMapLayer::VectorLayer )
{
mLayer = new QgsVectorLayer( uri, QString(), providerKey);
}
if ( type == QgsMapLayer::RasterLayer )
{
// This should go to WMS provider
QStringList URIParts = uri.split( "|" );
QString rasterLayerPath = URIParts.at( 0 );
QStringList layers;
QStringList styles;
QString format;
QString crs;
for ( int i = 1 ; i < URIParts.size(); i++ )
{
QString part = URIParts.at( i );
int pos = part.indexOf( "=" );
QString field = part.left( pos );
QString value = part.mid( pos + 1 );
if ( field == "layers" ) layers = value.split(",");
if ( field == "styles" ) styles = value.split(",");
if ( field == "format" ) format = value;
if ( field == "crs" ) crs = value;
}
QgsDebugMsg ( "rasterLayerPath = " + rasterLayerPath );
QgsDebugMsg ( "layers = " + layers.join(" " ) );
mLayer = new QgsRasterLayer( 0, rasterLayerPath, "", providerKey, layers, styles, format, crs );
}
}
if ( mLayer && mLayer->isValid() )
{
QgsDebugMsg ( "Layer created");
QgsMapLayerRegistry::instance()->addMapLayer(mLayer);
metaEnable = true;
previewEnable = true;
if ( mLayer->type() == QgsMapLayer::VectorLayer ) {
attributesEnable = true;
}
// force update of the current tab
updateCurrentTab();
}
else
{
qDebug("No layer" );
}
int selected = -1;
if ( mLastTab.contains( typeid(*ptr).name() ) )
{
selected = mLastTab[ typeid(*ptr).name()];
}
// Enabling tabs call tabChanged !
tabWidget->setTabEnabled ( tabWidget->indexOf( paramTab ), paramEnable);
tabWidget->setTabEnabled ( tabWidget->indexOf( metaTab ), metaEnable );
tabWidget->setTabEnabled ( tabWidget->indexOf( previewTab ), previewEnable );
tabWidget->setTabEnabled ( tabWidget->indexOf( attributesTab ), attributesEnable );
// select tab according last selection for this data item
if ( selected >= 0 )
{
qDebug("set tab %s %d", typeid(*ptr).name(), selected );
tabWidget->setCurrentIndex ( selected );
}
qDebug("clicked: %d %d %s", index.row(), index.column(), ptr->mName.toAscii().data());
}
void QgsBrowser::itemDoubleClicked(const QModelIndex& index)
{
QgsDataItem* ptr = (QgsDataItem*) index.internalPointer();
ptr->doubleClick();
qDebug("doubleclicked: %d %d %s", index.row(), index.column(), ptr->mName.toAscii().data());
}
void QgsBrowser::itemExpanded(const QModelIndex& index)
{
QSettings settings;
QgsDataItem* ptr = (QgsDataItem*) index.internalPointer();
/*
if (ptr->mType == QgsDataItem::Directory || ptr->mType == QgsDataItem::Collection )
{
QgsDirectoryItem* i = (QgsDirectoryItem*) ptr;
settings.setValue ( "/Browser/lastExpandedDir", i->mPath );
}
*/
// TODO: save separately each type (FS, WMS)
settings.setValue ( "/Browser/lastExpanded", ptr->mPath );
QgsDebugMsg( "last expanded: " + ptr->mPath );
}
void QgsBrowser::newVectorLayer()
{
// Set file dialog to last selected dir
QSettings settings;
QString lastPath = settings.value ( "/Browser/lastExpanded" ).toString();
if ( !lastPath.isEmpty() )
{
settings.setValue( "/UI/lastVectorFileFilterDir", lastPath );
}
QString fileName = QgsNewVectorLayerDialog::runAndCreateLayer( this );
if ( !fileName.isEmpty() )
{
QgsDebugMsg( "New vector layer: " + fileName );
expand( fileName );
QFileInfo fileInfo ( fileName );
QString dirPath = fileInfo.absoluteDir().path();
mModel->refresh ( dirPath );
}
}
void QgsBrowser::on_mActionWmsConnections_triggered()
{
QDialog *wmss = dynamic_cast<QDialog*> ( QgsProviderRegistry::instance()->getSelectWidget( QString("wms"), this ) );
if ( !wmss )
{
QMessageBox::warning( this, tr( "WMS" ), tr( "Cannot get WMS select dialog from provider." ) );
return;
}
wmss->exec();
delete wmss;
// TODO: refresh only WMS
refresh();
}
void QgsBrowser::on_mActionSetProjection_triggered()
{
if ( !mLayer ) { return; }
QgsGenericProjectionSelector * mySelector = new QgsGenericProjectionSelector( this );
mySelector->setMessage();
mySelector->setSelectedCrsId( mLayer->crs().srsid() );
if ( mySelector->exec() )
{
QgsCoordinateReferenceSystem srs( mySelector->selectedCrsId(), QgsCoordinateReferenceSystem::InternalCrsId );
// TODO: open data source in write mode set crs and save
//mLayer->setCrs( srs );
// Is this safe?
// selectedIndexes() is protected
QgsDataItem* ptr = (QgsDataItem*) mIndex.internalPointer();
if ( ! ptr->setCrs ( srs ) )
{
QMessageBox::critical( this, tr( "CRS" ), tr( "Cannot set layer CRS" ));
}
QgsDebugMsg( srs.authid() + " - " + srs.description() );
}
else
{
QApplication::restoreOverrideCursor();
}
delete mySelector;
}
void QgsBrowser::saveWindowState()
{
QSettings settings;
settings.setValue( "/Windows/Browser/state", saveState() );
settings.setValue( "/Windows/Browser/geometry", saveGeometry() );
settings.setValue( "/Windows/Browser/sizes/0", splitter->sizes()[0] );
settings.setValue( "/Windows/Browser/sizes/1", splitter->sizes()[1] );
}
void QgsBrowser::restoreWindowState()
{
QSettings settings;
if ( !restoreState( settings.value( "/Windows/Browser/state" ).toByteArray() ) )
{
QgsDebugMsg( "restore of UI state failed" );
}
if ( !restoreGeometry( settings.value( "/Windows/Browser/geometry" ).toByteArray() ) )
{
QgsDebugMsg( "restore of UI geometry failed" );
}
int size0 = settings.value( "/Windows/Browser/sizes/0" ).toInt();
if ( size0 > 0 )
{
QList<int> sizes;
sizes << size0;
sizes << settings.value( "/Windows/Browser/sizes/1" ).toInt();
QgsDebugMsg( QString("set splitter sizes to %1 %2").arg(sizes[0]).arg(sizes[1]) );
splitter->setSizes(sizes);
}
}
void QgsBrowser::keyPressEvent( QKeyEvent * e )
{
QgsDebugMsg( "Entered");
if ( e->key() == Qt::Key_Escape )
{
stopRendering();
}
else
{
e->ignore();
}
}
void QgsBrowser::stopRendering()
{
// you might have seen this already in QgisApp
QgsDebugMsg( "Entered");
if ( mapCanvas )
{
QgsMapRenderer* mypMapRenderer = mapCanvas->mapRenderer();
if ( mypMapRenderer )
{
QgsRenderContext* mypRenderContext = mypMapRenderer->rendererContext();
if ( mypRenderContext )
{
mypRenderContext->setRenderingStopped( true );
}
}
}
}
QgsBrowser::Tab QgsBrowser::activeTab()
{
QWidget* curr = tabWidget->currentWidget();
if (curr == metaTab)
return Metadata;
if (curr == previewTab)
return Preview;
return Attributes;
}
void QgsBrowser::updateCurrentTab()
{
// update contents of the current tab
Tab current = activeTab();
if (current == Metadata && mDirtyMetadata)
{
if (mLayer)
{
// Set meta
QString myStyle = QgsApplication::reportStyleSheet();
metaTextBrowser->document()->setDefaultStyleSheet( myStyle );
metaTextBrowser->setHtml( mLayer->metadata() );
}
else
{
metaTextBrowser->setHtml(QString());
}
mDirtyMetadata = false;
}
if (current == Preview && mDirtyPreview)
{
if (mLayer)
{
// Create preview: add to map canvas
QList<QgsMapCanvasLayer> layers;
layers << QgsMapCanvasLayer(mLayer);
mapCanvas->setLayerSet(layers);
QgsRectangle fullExtent = mLayer->extent();
fullExtent.scale(1.05); // add some border
mapCanvas->setExtent(fullExtent);
mapCanvas->refresh();
}
mDirtyPreview = false;
}
if (current == Attributes && mDirtyAttributes)
{
if ( mLayer && mLayer->type() == QgsMapLayer::VectorLayer )
{
QgsVectorLayer* vlayer = qobject_cast<QgsVectorLayer*>( mLayer );
QApplication::setOverrideCursor(Qt::WaitCursor);
attributeTable->setLayer( vlayer );
QApplication::restoreOverrideCursor();
}
else
{
attributeTable->setLayer( NULL );
}
mDirtyAttributes = false;
}
}
void QgsBrowser::tabChanged()
{
updateCurrentTab();
// Store last selected tab for selected data item
if ( mIndex.isValid() )
{
QObject* ptr = (QObject*) mIndex.internalPointer();
QgsDebugMsg( QString("save last tab %1 : %2").arg( typeid(*ptr).name() ).arg(tabWidget->currentIndex()) );
mLastTab[typeid(*ptr).name()] = tabWidget->currentIndex();
}
}
void QgsBrowser::on_mActionRefresh_triggered()
{
QgsDebugMsg( "Entered" );
refresh();
}
void QgsBrowser::refresh( const QModelIndex& index )
{
QgsDebugMsg( "Entered" );
if ( index.isValid() )
{
QgsDataItem* item = (QgsDataItem*) index.internalPointer();
QgsDebugMsg( "path = " + item->mPath );
}
mModel->refresh( index );
for ( int i = 0 ; i < mModel->rowCount(index); i++ )
{
QModelIndex idx = mModel->index(i, 0, index);
if ( treeView->isExpanded ( idx ) )
{
refresh( idx );
}
}
}

81
src/browser/qgsbrowser.h Normal file
View File

@ -0,0 +1,81 @@
/***************************************************************************
qgsbrowser.h - Data sources browser
-------------------
begin : 2011-04-01
copyright : (C) 2011 Radim Blazek
email : radim dot blazek at gmail 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. *
* *
***************************************************************************/
/* $Id$ */
#ifndef QGSBROWSER_H
#define QGSBROWSER_H
#include <QMainWindow>
#include <QMap>
#include <QModelIndex>
#include "ui_qgsbrowserbase.h"
class QgsBrowserModel;
class QgsMapLayer;
class QgsBrowser : public QMainWindow, private Ui::QgsBrowserBase
{
Q_OBJECT
public:
QgsBrowser( QWidget *parent = 0, Qt::WFlags flags = 0 );
~QgsBrowser();
// Expand to given path
void expand ( QString path, const QModelIndex& index = QModelIndex() );
public slots:
void itemClicked(const QModelIndex& index);
void itemDoubleClicked(const QModelIndex& index);
void itemExpanded(const QModelIndex& index);
void on_mActionSetProjection_triggered();
void on_mActionWmsConnections_triggered();
void on_mActionRefresh_triggered();
void newVectorLayer();
void saveWindowState();
void restoreWindowState();
void tabChanged();
void updateCurrentTab();
void stopRendering();
// Refresh all leaf or expanded items
void refresh ( const QModelIndex& index= QModelIndex() );
protected:
void keyPressEvent( QKeyEvent * e );
enum Tab
{
Metadata,
Preview,
Attributes
};
Tab activeTab();
bool mDirtyMetadata, mDirtyPreview, mDirtyAttributes;
QgsBrowserModel* mModel;
QgsMapLayer *mLayer;
QModelIndex mIndex;
QWidget *mParamWidget;
// last (selected) tab for each
QMap<QString,int> mLastTab;
};
#endif // QGSBROWSER_H

View File

@ -0,0 +1,246 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>QgsBrowserBase</class>
<widget class="QMainWindow" name="QgsBrowserBase">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>714</width>
<height>471</height>
</rect>
</property>
<property name="windowTitle">
<string>QGIS Browser</string>
</property>
<widget class="QWidget" name="centralwidget">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QSplitter" name="splitter">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>696</width>
<height>0</height>
</size>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<widget class="QTreeView" name="treeView">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
<horstretch>1</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
<widget class="QTabWidget" name="tabWidget">
<property name="enabled">
<bool>true</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>3</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="currentIndex">
<number>1</number>
</property>
<widget class="QWidget" name="paramTab">
<property name="enabled">
<bool>true</bool>
</property>
<attribute name="title">
<string>Param</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_5">
<item>
<layout class="QVBoxLayout" name="paramLayout"/>
</item>
</layout>
</widget>
<widget class="QWidget" name="metaTab">
<property name="enabled">
<bool>true</bool>
</property>
<attribute name="title">
<string>Metadata</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QTextBrowser" name="metaTextBrowser"/>
</item>
</layout>
</widget>
<widget class="QWidget" name="previewTab">
<property name="enabled">
<bool>true</bool>
</property>
<attribute name="title">
<string>Preview</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QgsMapCanvas" name="mapCanvas"/>
</item>
<item>
<widget class="QWidget" name="widget" native="true">
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>370</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="stopRenderingButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Stop rendering</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="attributesTab">
<property name="enabled">
<bool>true</bool>
</property>
<attribute name="title">
<string>Attributes</string>
</attribute>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QgsAttributeTableView" name="attributeTable"/>
</item>
</layout>
</widget>
</widget>
</widget>
</item>
</layout>
</widget>
<widget class="QToolBar" name="toolBar">
<property name="windowTitle">
<string>toolBar</string>
</property>
<property name="movable">
<bool>false</bool>
</property>
<property name="toolButtonStyle">
<enum>Qt::ToolButtonTextBesideIcon</enum>
</property>
<property name="floatable">
<bool>false</bool>
</property>
<attribute name="toolBarArea">
<enum>TopToolBarArea</enum>
</attribute>
<attribute name="toolBarBreak">
<bool>false</bool>
</attribute>
<addaction name="mActionRefresh"/>
<addaction name="mActionWmsConnections"/>
<addaction name="mActionNewVectorLayer"/>
<addaction name="mActionSetProjection"/>
</widget>
<action name="mActionNewVectorLayer">
<property name="icon">
<iconset resource="../../images/images.qrc">
<normaloff>:/images/themes/default/mActionNewVectorLayer.png</normaloff>:/images/themes/default/mActionNewVectorLayer.png</iconset>
</property>
<property name="text">
<string>New Shapefile</string>
</property>
<property name="shortcut">
<string>Ctrl+Shift+N</string>
</property>
</action>
<action name="mActionRefresh">
<property name="icon">
<iconset resource="../../images/images.qrc">
<normaloff>:/images/themes/default/mActionDraw.png</normaloff>:/images/themes/default/mActionDraw.png</iconset>
</property>
<property name="text">
<string>Refresh</string>
</property>
<property name="shortcut">
<string>Ctrl+R</string>
</property>
</action>
<action name="mActionSetProjection">
<property name="enabled">
<bool>false</bool>
</property>
<property name="icon">
<iconset resource="../../images/images.qrc">
<normaloff>:/images/themes/default/mActionCustomProjection.png</normaloff>:/images/themes/default/mActionCustomProjection.png</iconset>
</property>
<property name="text">
<string>Set layer CRS</string>
</property>
<property name="toolTip">
<string>Set layer CRS</string>
</property>
</action>
<action name="mActionWmsConnections">
<property name="icon">
<iconset resource="../../images/images.qrc">
<normaloff>:/images/themes/default/mActionAddWmsLayer.png</normaloff>:/images/themes/default/mActionAddWmsLayer.png</iconset>
</property>
<property name="text">
<string>Manage WMS</string>
</property>
<property name="toolTip">
<string>Manage WMS Connections</string>
</property>
<property name="shortcut">
<string>Ctrl+Shift+W</string>
</property>
</action>
</widget>
<customwidgets>
<customwidget>
<class>QgsMapCanvas</class>
<extends>QGraphicsView</extends>
<header>qgsmapcanvas.h</header>
</customwidget>
<customwidget>
<class>QgsAttributeTableView</class>
<extends>QTableView</extends>
<header>qgsattributetableview.h</header>
</customwidget>
</customwidgets>
<resources>
<include location="../../images/images.qrc"/>
</resources>
<connections/>
</ui>

View File

@ -0,0 +1,314 @@
#include <QDir>
#include <QApplication>
#include <QStyle>
#include "qgis.h"
#include "qgsapplication.h"
#include "qgsdataprovider.h"
#include "qgslogger.h"
#include "qgsproviderregistry.h"
#include "qgsbrowsermodel.h"
// TODO: bad place, where to put this? qgsproviderregistry?
typedef int dataCapabilities_t();
typedef QgsDataItem * dataItem_t(QString);
QgsBrowserModel::QgsBrowserModel(QObject *parent) :
QAbstractItemModel(parent)
{
QStyle *style = QApplication::style();
mIconDirectory = QIcon( style->standardPixmap( QStyle::SP_DirClosedIcon ) );
mIconDirectory.addPixmap( style->standardPixmap( QStyle::SP_DirOpenIcon ),
QIcon::Normal, QIcon::On );
foreach (QFileInfo drive, QDir::drives())
{
QString path = drive.absolutePath();
QgsDirectoryItem *item = new QgsDirectoryItem(NULL, path, path);
connectItem(item);
mRootItems << item;
}
// Add non file top level items
foreach ( QString key, QgsProviderRegistry::instance()->providerList() )
{
QLibrary *library = QgsProviderRegistry::instance()->getLibrary(key);
if ( !library ) continue;
dataCapabilities_t * dataCapabilities = (dataCapabilities_t *) cast_to_fptr( library->resolve ("dataCapabilities") );
if ( !dataCapabilities ) {
QgsDebugMsg ( library->fileName() + " does not have dataCapabilities" );
continue;
}
int capabilities = dataCapabilities();
if ( capabilities == QgsDataProvider::NoDataCapabilities )
{
QgsDebugMsg ( library->fileName() + " does not have any dataCapabilities" );
continue;
}
dataItem_t * dataItem = (dataItem_t *) cast_to_fptr( library->resolve ("dataItem" ) );
if ( ! dataItem )
{
QgsDebugMsg ( library->fileName() + " does not have dataItem" );
continue;
}
QgsDataItem * item = dataItem ( "" ); // empty path -> top level
if ( item )
{
QgsDebugMsg ( "Add new top level item : " + item->mName );
connectItem(item);
mRootItems << item;
}
}
}
QgsBrowserModel::~QgsBrowserModel()
{
foreach (QgsDataItem* item, mRootItems)
delete item;
}
Qt::ItemFlags QgsBrowserModel::flags( const QModelIndex & index ) const
{
if (!index.isValid())
return 0;
return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
}
QVariant QgsBrowserModel::data( const QModelIndex & index, int role ) const
{
if (!index.isValid())
return QVariant();
QgsDataItem* ptr = (QgsDataItem*) index.internalPointer();
if (role == Qt::DisplayRole)
{
return QVariant(ptr->mName);
}
else if (role == Qt::DecorationRole && index.column() == 0)
{
return QVariant( ptr->icon() );
}
// unsupported role
return QVariant();
}
QVariant QgsBrowserModel::headerData( int section, Qt::Orientation orientation, int role ) const
{
if (orientation == Qt::Horizontal && role == Qt::DisplayRole)
{
return QVariant("header");
}
return QVariant();
}
int QgsBrowserModel::rowCount( const QModelIndex & parent ) const
{
//qDebug("rowCount: idx: (valid %d) %d %d", parent.isValid(), parent.row(), parent.column());
if (!parent.isValid())
{
// root item: its children are top level items
return mRootItems.count(); // mRoot
}
else
{
// ordinary item: number of its children
QgsDataItem* ptr = (QgsDataItem*) parent.internalPointer();
return ptr->rowCount();
}
}
bool QgsBrowserModel::hasChildren ( const QModelIndex & parent ) const
{
if (!parent.isValid())
{
return true; // root item: its children are top level items
}
else
{
QgsDataItem* ptr = (QgsDataItem*) parent.internalPointer();
return ptr->hasChildren();
}
return false;
}
int QgsBrowserModel::columnCount ( const QModelIndex & parent ) const
{
return 1;
}
QModelIndex QgsBrowserModel::index( int row, int column, const QModelIndex & parent ) const
{
//qDebug("index: idx: (valid %d) %d %d", parent.isValid(), parent.row(), parent.column());
if (!parent.isValid())
{
// this is the root item, parent of the top level items
Q_ASSERT(column == 0 && row >= 0 && row < mRootItems.count());
return createIndex(row,column, mRootItems[row]);
}
else
{
// this is ordinary item: return a valid index if the requested child exists
QgsDataItem* ptr = (QgsDataItem*) parent.internalPointer();
if (ptr->mType == QgsDataItem::Directory || ptr->mType == QgsDataItem::Collection)
{
// this is a directory: get index of its subdir!
QgsDirectoryItem* di = (QgsDirectoryItem*) ptr;
return createIndex(row, column, di->mChildren.at(row));
}
if (ptr->mType == QgsDataItem::Layer)
{
return QModelIndex(); // has no children
}
Q_ASSERT(false && "unknown item in index()");
}
return QModelIndex(); // if the child does not exist
}
QModelIndex QgsBrowserModel::index( QgsDataItem *item )
{
// Item index
QModelIndex index = QModelIndex();
const QVector<QgsDataItem*>& children = item->mParent ? item->mParent->mChildren : mRootItems;
Q_ASSERT( children.size() > 0 );
int row = -1;
for ( int i = 0; i < children.size(); i++ )
{
if ( item == children[i] )
{
row = i;
break;
}
}
QgsDebugMsg( QString ( "row = %1").arg(row) );
Q_ASSERT( row >= 0 );
index = createIndex( row, 0, item );
return index;
}
QModelIndex QgsBrowserModel::parent( const QModelIndex & index ) const
{
if (!index.isValid())
return QModelIndex();
// return QModelInde of parent, i.e. where the parent is within its parent :-)
//qDebug("parent of: %d %d", index.row(), index.column());
QgsDataItem* ptr = (QgsDataItem*) index.internalPointer();
QgsDataItem* parentItem = ptr->mParent;
if (parentItem == NULL)
{
// parent of our root is invalid index
return QModelIndex();
}
const QVector<QgsDataItem*>& children =
parentItem->mParent ? ((QgsDirectoryItem*)parentItem->mParent)->mChildren : mRootItems;
Q_ASSERT(children.count() > 0);
for (int i = 0; i < children.count(); i++)
{
if (children[i] == parentItem)
return createIndex(i, 0, parentItem);
}
Q_ASSERT(false && "parent not found!");
return QModelIndex();
}
/* Refresh dir path */
void QgsBrowserModel::refresh( QString path, const QModelIndex& theIndex )
{
QStringList paths = path.split('/');
for ( int i = 0; i < rowCount(theIndex); i++ )
{
QModelIndex idx = index(i, 0, theIndex);
QgsDataItem* ptr = (QgsDataItem*) idx.internalPointer();
if ( ptr->mPath == path )
{
QgsDebugMsg( "Arrived " + ptr->mPath );
ptr->refresh();
return;
}
if ( path.indexOf ( ptr->mPath ) == 0 )
{
refresh( path, idx );
break;
}
}
}
/* Refresh item */
void QgsBrowserModel::refresh( const QModelIndex& theIndex )
{
if ( !theIndex.isValid () ) // root
{
// Nothing to do I believe, mRootItems are always the same
}
else
{
QgsDataItem* ptr = (QgsDataItem*) theIndex.internalPointer();
QgsDebugMsg( "Refresh " + ptr->mPath );
ptr->refresh();
}
}
void QgsBrowserModel::beginInsertItems( QgsDataItem* parent, int first, int last )
{
QgsDebugMsg( "parent mPath = " + parent->mPath );
QModelIndex idx = index( parent );
if ( !idx.isValid() ) return;
QgsDebugMsg( "valid");
beginInsertRows( idx, first, last );
QgsDebugMsg( "end");
}
void QgsBrowserModel::endInsertItems()
{
QgsDebugMsg( "Entered");
endInsertRows();
}
void QgsBrowserModel::beginRemoveItems( QgsDataItem* parent, int first, int last )
{
QgsDebugMsg( "parent mPath = " + parent->mPath );
QModelIndex idx = index( parent );
if ( !idx.isValid() ) return;
beginRemoveRows( idx, first, last );
}
void QgsBrowserModel::endRemoveItems()
{
QgsDebugMsg( "Entered");
endRemoveRows();
}
void QgsBrowserModel::connectItem ( QgsDataItem* item )
{
connect ( item, SIGNAL(beginInsertItems ( QgsDataItem*, int, int )),
this, SLOT(beginInsertItems( QgsDataItem*, int, int )) );
connect ( item, SIGNAL(endInsertItems ()),
this, SLOT(endInsertItems()) );
connect ( item, SIGNAL(beginRemoveItems ( QgsDataItem*, int, int )),
this, SLOT(beginRemoveItems( QgsDataItem*, int, int )) );
connect ( item, SIGNAL(endRemoveItems ()),
this, SLOT(endRemoveItems()) );
}

View File

@ -0,0 +1,70 @@
#ifndef QGSBROWSERMODEL_H
#define QGSBROWSERMODEL_H
#include <QAbstractItemModel>
#include <QIcon>
#include "qgsdataitem.h"
class QgsBrowserModel : public QAbstractItemModel
{
Q_OBJECT
public:
explicit QgsBrowserModel(QObject *parent = 0);
~QgsBrowserModel();
// implemented methods from QAbstractItemModel for read-only access
/** Used by other components to obtain information about each item provided by the model.
In many models, the combination of flags should include Qt::ItemIsEnabled and Qt::ItemIsSelectable. */
virtual Qt::ItemFlags flags( const QModelIndex & index ) const;
/** Used to supply item data to views and delegates. Generally, models only need to supply data
for Qt::DisplayRole and any application-specific user roles, but it is also good practice
to provide data for Qt::ToolTipRole, Qt::AccessibleTextRole, and Qt::AccessibleDescriptionRole.
See the Qt::ItemDataRole enum documentation for information about the types associated with each role. */
virtual QVariant data( const QModelIndex & index, int role = Qt::DisplayRole ) const;
/** Provides views with information to show in their headers. The information is only retrieved
by views that can display header information. */
virtual QVariant headerData( int section, Qt::Orientation orientation, int role = Qt::DisplayRole ) const;
/** Provides the number of rows of data exposed by the model. */
virtual int rowCount( const QModelIndex & parent = QModelIndex() ) const;
/** Provides the number of columns of data exposed by the model. List models do not provide this function
because it is already implemented in QAbstractListModel. */
virtual int columnCount ( const QModelIndex & parent = QModelIndex() ) const;
/** Returns the index of the item in the model specified by the given row, column and parent index. */
virtual QModelIndex index( int row, int column, const QModelIndex & parent = QModelIndex() ) const;
QModelIndex index( QgsDataItem *item );
/** Returns the parent of the model item with the given index. If the item has no parent, an invalid QModelIndex is returned. */
virtual QModelIndex parent( const QModelIndex & index ) const;
bool hasChildren ( const QModelIndex & parent = QModelIndex() ) const;
// Refresh item specified by path
void refresh( QString path, const QModelIndex& index = QModelIndex() );
// Refresh item childs
void refresh( const QModelIndex& index = QModelIndex() );
void connectItem ( QgsDataItem * item );
signals:
public slots:
//void removeItems( QgsDataItem * parent, QVector<QgsDataItem *>items );
//void addItems( QgsDataItem * parent, QVector<QgsDataItem *>items );
//void refreshItems( QgsDataItem * parent, QVector<QgsDataItem *>items );
void beginInsertItems( QgsDataItem* parent, int first, int last );
void endInsertItems();
void beginRemoveItems( QgsDataItem* parent, int first, int last );
void endRemoveItems();
protected:
QVector<QgsDataItem*> mRootItems;
QIcon mIconDirectory;
};
#endif // QGSBROWSERMODEL_H

18
src/browser/template.cpp Normal file
View File

@ -0,0 +1,18 @@
/***************************************************************************
qgs.cpp -
-------------------
begin : 2011-04-01
copyright : (C) 2011 Radim Blazek
email : radim dot blazek at gmail 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. *
* *
***************************************************************************/
/* $Id$ */

22
src/browser/template.h Normal file
View File

@ -0,0 +1,22 @@
/***************************************************************************
qgs.h -
-------------------
begin : 2011-04-01
copyright : (C) 2011 Radim Blazek
email : radim dot blazek at gmail 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. *
* *
***************************************************************************/
/* $Id$ */
#ifndef QGS_H
#define QGS_H
#endif // QGS_H

View File

@ -46,6 +46,7 @@ SET(QGIS_CORE_SRCS
qgscontexthelp.cpp
qgscoordinatetransform.cpp
qgsdatasourceuri.cpp
qgsdataitem.cpp
qgsdiagram.cpp
qgsdiagramrendererv2.cpp
qgsdistancearea.cpp
@ -78,6 +79,7 @@ SET(QGIS_CORE_SRCS
qgsproviderextentcalcevent.cpp
qgsprovidermetadata.cpp
qgsproviderregistry.cpp
qgspythonrunner.cpp
qgsrasterprojector.cpp
qgsrasterdataprovider.cpp
qgsrendercontext.cpp
@ -219,6 +221,7 @@ SET(QGIS_CORE_MOC_HDRS
qgsapplication.h
qgscontexthelp.h
qgscoordinatetransform.h
qgsdataitem.h
qgsdataprovider.h
qgshttptransaction.h
qgsmaplayer.h
@ -381,6 +384,7 @@ SET(QGIS_CORE_HDRS
qgscontexthelp.h
qgscoordinatetransform.h
qgsdatasourceuri.h
qgsdataitem.h
qgsdistancearea.h
qgscsexception.h
qgsexception.h
@ -411,6 +415,7 @@ SET(QGIS_CORE_HDRS
qgsproviderextentcalcevent.h
qgsprovidermetadata.h
qgsproviderregistry.h
qgspythonrunner.h
qgsrasterprojector.h
qgsrasterdataprovider.h
qgsrectangle.h

View File

@ -15,6 +15,7 @@
/* $Id$ */
#include "qgsapplication.h"
#include "qgslogger.h"
#include "qgsmaplayerregistry.h"
#include "qgsproviderregistry.h"
#include "qgsexception.h"
@ -111,8 +112,13 @@ bool QgsApplication::event( QEvent * event )
bool QgsApplication::notify( QObject * receiver, QEvent * event )
{
bool done = false;
emit preNotify( receiver, event, &done );
if ( done ) return true;
// Send event to receiver and catch unhandled exceptions
bool done = true;
done = true;
try
{
done = QApplication::notify( receiver, event );
@ -129,6 +135,7 @@ bool QgsApplication::notify( QObject * receiver, QEvent * event )
{
QMessageBox::critical( activeWindow(), tr( "Exception" ), tr( "unknown exception" ) );
}
return done;
}

View File

@ -201,6 +201,9 @@ class CORE_EXPORT QgsApplication: public QApplication
@note: this method was added in version 1.6*/
static QString relativePathToAbsolutePath( QString rpath, QString targetPath );
signals:
void preNotify( QObject * receiver, QEvent * event, bool * done );
private:
static QObject* mFileOpenEventReceiver;
static QStringList mFileOpenEventList;

View File

@ -29,6 +29,7 @@
#include <QDomElement>
#include "qgsattributeaction.h"
#include "qgspythonrunner.h"
#include "qgsrunprocess.h"
#include "qgsvectorlayer.h"
@ -67,12 +68,18 @@ void QgsAttributeAction::doAction( int index, const QgsAttributeMap &attributes,
{
if ( executePython )
{
// deprecated
executePython( expandedAction );
}
else if ( smPythonExecute )
{
// deprecated
smPythonExecute( expandedAction );
}
else
{
QgsPythonRunner::run( expandedAction );
}
}
else
{

View File

@ -136,6 +136,7 @@ class CORE_EXPORT QgsAttributeAction
QgsAction &at( int idx ) { return mActions[idx]; }
QgsAction &operator[]( int idx ) { return mActions[idx]; }
//! @deprecated Initialize QgsPythonRunner instead
static void setPythonExecute( void ( * )( const QString & ) );
private:

514
src/core/qgsdataitem.cpp Normal file
View File

@ -0,0 +1,514 @@
/***************************************************************************
qgsdataitem.cpp - Data items
-------------------
begin : 2011-04-01
copyright : (C) 2011 Radim Blazek
email : radim dot blazek at gmail 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. *
* *
***************************************************************************/
/* $Id$ */
#include <typeinfo>
#include <QApplication>
#include <QDateTime>
#include <QDir>
#include <QFileInfo>
#include <QMenu>
#include <QMouseEvent>
#include <QTreeWidget>
#include <QTreeWidgetItem>
#include <QVector>
#include <QStyle>
#include <QSettings>
#include "qgis.h"
#include "qgsapplication.h"
#include "qgsdataitem.h"
#include "qgsdataprovider.h"
#include "qgslogger.h"
#include "qgsproviderregistry.h"
QgsDataItem::QgsDataItem(QgsDataItem::Type type, QgsDataItem* parent, QString name, QString path)
: QObject(parent), mType(type), mParent(parent), mPopulated(false), mName(name), mPath(path)
{
}
QIcon QgsDataItem::icon()
{
if ( !mIcon.isNull() ) return mIcon;
return mDefaultIcon;
}
// TODO: This is copy from QgisApp, bad
// TODO: add some caching mechanism ?
QPixmap QgsDataItem::getThemePixmap( const QString theName )
{
QString myPreferredPath = QgsApplication::activeThemePath() + QDir::separator() + theName;
QString myDefaultPath = QgsApplication::defaultThemePath() + QDir::separator() + theName;
//QgsDebugMsg( "myPreferredPath = " + myPreferredPath );
//QgsDebugMsg( "myDefaultPath = " + myDefaultPath );
if ( QFile::exists( myPreferredPath ) )
{
return QPixmap( myPreferredPath );
}
else
{
//could still return an empty icon if it
//doesnt exist in the default theme either!
return QPixmap( myDefaultPath );
}
}
void QgsDataItem::doubleClick()
{
}
void QgsDataItem::emitBeginInsertItems( QgsDataItem* parent, int first, int last )
{
emit beginInsertItems ( parent, first, last );
}
void QgsDataItem::emitEndInsertItems()
{
emit endInsertItems();
}
void QgsDataItem::emitBeginRemoveItems( QgsDataItem* parent, int first, int last )
{
emit beginRemoveItems ( parent, first, last );
}
void QgsDataItem::emitEndRemoveItems()
{
emit endRemoveItems();
}
QVector<QgsDataItem*> QgsDataItem::createChildren( )
{
QVector<QgsDataItem*> children;
return children;
}
void QgsDataItem::populate()
{
QVector<QgsDataItem*> children = createChildren( );
foreach ( QgsDataItem *child, children )
{
// initialization, do not refresh! That would result in infinite loop (beginInsertItems->rowCount->populate)
addChildItem ( child);
}
mPopulated = true;
}
int QgsDataItem::rowCount()
{
if (!mPopulated) populate();
return mChildren.size();
}
bool QgsDataItem::hasChildren()
{
return ( mPopulated ? mChildren.count() > 0 : true);
}
void QgsDataItem::addChildItem ( QgsDataItem * child, bool refresh )
{
QgsDebugMsg( "mName = " + child->mName );
int i;
for ( i = 0; i < mChildren.size(); i++ )
{
if ( mChildren[i]->mName.localeAwareCompare ( child->mName ) >= 0 ) break;
}
if ( refresh ) emit beginInsertItems ( this, i, i );
child->setParent(this);
mChildren.insert ( i, child );
connect ( child, SIGNAL(beginInsertItems ( QgsDataItem*, int, int )),
this, SLOT(emitBeginInsertItems( QgsDataItem*, int, int )) );
connect ( child, SIGNAL(endInsertItems ()),
this, SLOT(emitEndInsertItems()) );
connect ( child, SIGNAL(beginRemoveItems ( QgsDataItem*, int, int )),
this, SLOT(emitBeginRemoveItems( QgsDataItem*, int, int )) );
connect ( child, SIGNAL(endRemoveItems ()),
this, SLOT(emitEndRemoveItems()) );
if ( refresh ) emit endInsertItems();
}
void QgsDataItem::deleteChildItem ( QgsDataItem * child )
{
QgsDebugMsg( "mName = " + child->mName );
int i = mChildren.indexOf( child );
Q_ASSERT( i >= 0 );
emit beginRemoveItems ( this, i, i );
mChildren.remove(i);
delete child;
emit endRemoveItems ();
}
int QgsDataItem::findItem ( QVector<QgsDataItem*> items, QgsDataItem * item )
{
for ( int i = 0; i < items.size(); i++ )
{
QgsDebugMsg( QString::number(i) + " : " + items[i]->mPath + " x " + item->mPath );
if ( items[i]->equal ( item ) ) return i;
}
return -1;
}
void QgsDataItem::refresh()
{
QgsDebugMsg ( "mPath = " + mPath );
QVector<QgsDataItem*> items = createChildren( );
// Remove no more present items
QVector<QgsDataItem*> remove;
foreach ( QgsDataItem *child, mChildren )
{
if ( findItem(items, child ) >= 0 ) continue;
remove.append ( child );
}
foreach ( QgsDataItem *child, remove )
{
deleteChildItem ( child );
}
// Add new items
foreach ( QgsDataItem *item, items )
{
// Is it present in childs?
if ( findItem ( mChildren, item ) >= 0 )
{
delete item;
continue;
}
addChildItem ( item, true );
}
}
// ---------------------------------------------------------------------
QgsLayerItem::QgsLayerItem(QgsDataItem* parent, QString name, QString path)
: QgsDataItem(Layer, parent, name, path)
{
}
QgsLayerItem::QgsLayerItem(QgsDataItem* parent, QgsDataItem::Type type, QString name, QString path, QString uri)
: QgsDataItem(type, parent, name, path), mUri(uri)
{
}
QIcon QgsLayerItem::icon()
{
if ( !mIcon.isNull() ) return mIcon;
QString name;
switch ( mType )
{
case QgsDataItem::Point:
name = "/mIconPointLayer.png";
break;
case QgsDataItem::Line:
name = "/mIconLineLayer.png";
break;
case QgsDataItem::Polygon:
name = "/mIconPolygonLayer.png";
break;
case QgsDataItem::TableLayer:
name = "/mIconTableLayer.png";
break;
default:
name = "/mIconLayer.png";
break;
}
//QgsDebugMsg( QString ( "mType = %1 name = %2").arg ( mType).arg (name ) );
if ( !name.isEmpty() )
{
QPixmap pixmap = getThemePixmap ( name );
//QgsDebugMsg( QString ( "pixmap.isNull = %1").arg(pixmap.isNull() ) );
return QIcon ( pixmap );
}
return mDefaultIcon;
}
bool QgsLayerItem::equal(const QgsDataItem *other)
{
//QgsDebugMsg ( mPath + " x " + other->mPath );
if ( typeid ( *this ) != typeid ( *other ) )
{
//QgsDebugMsg ( "different typeid" );
return false;
}
//const QgsLayerItem *o = qobject_cast<const QgsLayerItem *> ( other );
const QgsLayerItem *o = dynamic_cast<const QgsLayerItem *> ( other );
return ( mPath == o->mPath && mName == o->mName && mUri == o->mUri && mProvider == o->mProvider );
}
// ---------------------------------------------------------------------
QgsDataCollectionItem::QgsDataCollectionItem( QgsDataItem::Type type, QgsDataItem* parent, QString name, QString path)
: QgsDataItem( type, parent, name, path)
{
QStyle *style = QApplication::style();
mDefaultIcon = QIcon( style->standardPixmap( QStyle::SP_DirClosedIcon ) );
mDefaultIcon.addPixmap( style->standardPixmap( QStyle::SP_DirOpenIcon ),
QIcon::Normal, QIcon::On );
}
QgsDataCollectionItem::~QgsDataCollectionItem()
{
foreach (QgsDataItem* i, mChildren)
delete i;
}
//-----------------------------------------------------------------------
QVector<QgsDataProvider*> QgsDirectoryItem::mProviders = QVector<QgsDataProvider*>();
QVector<QLibrary*> QgsDirectoryItem::mLibraries = QVector<QLibrary*>();
// TODO: bad place, where to put this? qgsproviderregistry.h?
typedef int dataCapabilities_t();
typedef QgsDataItem * dataItem_t(QString);
QgsDirectoryItem::QgsDirectoryItem(QgsDataItem* parent, QString name, QString path)
: QgsDataCollectionItem(Directory, parent, name, path)
{
if ( mLibraries.size() == 0 ) {
QStringList keys = QgsProviderRegistry::instance()->providerList();
QStringList::const_iterator i;
for ( i = keys.begin(); i != keys.end(); ++i)
{
QString k(*i);
// some providers hangs with empty uri (Postgis) etc...
// -> using libraries directly
QLibrary *library = QgsProviderRegistry::instance()->getLibrary(k);
if ( library )
{
dataCapabilities_t * dataCapabilities = (dataCapabilities_t *) cast_to_fptr( library->resolve ("dataCapabilities") );
if ( !dataCapabilities )
{
QgsDebugMsg ( library->fileName() + " does not have dataCapabilities" );
continue;
}
if ( dataCapabilities() == QgsDataProvider::NoDataCapabilities )
{
QgsDebugMsg ( library->fileName() + " does not have File capability" );
continue;
}
mLibraries.append( library );
}
else
{
//QgsDebugMsg ( "Cannot get provider " + k );
}
}
}
}
QgsDirectoryItem::~QgsDirectoryItem()
{
}
QVector<QgsDataItem*> QgsDirectoryItem::createChildren( )
{
QVector<QgsDataItem*> children;
QDir dir(mPath);
QStringList entries = dir.entryList(QDir::AllDirs | QDir::NoDotAndDotDot, QDir::Name | QDir::IgnoreCase);
foreach (QString subdir, entries)
{
QString subdirPath = dir.absoluteFilePath(subdir);
qDebug("creating subdir: %s", subdirPath.toAscii().data());
QgsDirectoryItem *item = new QgsDirectoryItem(this, subdir, subdirPath);
// propagate signals up to top
children.append( item );
}
QStringList fileEntries = dir.entryList( QDir::Files, QDir::Name);
foreach (QString name, fileEntries)
{
QString path = dir.absoluteFilePath( name );
foreach ( QLibrary *library, mLibraries )
{
// we could/should create separate list of providers for each purpose
// TODO: use existing fileVectorFilters(),directoryDrivers() ?
dataCapabilities_t * dataCapabilities = (dataCapabilities_t *) cast_to_fptr( library->resolve ("dataCapabilities") );
if ( !dataCapabilities ) continue;
int capabilities = dataCapabilities();
if ( ! (capabilities & QgsDataProvider::File) ) continue;
dataItem_t * dataItem = (dataItem_t *) cast_to_fptr( library->resolve ("dataItem" ) );
if ( ! dataItem )
{
QgsDebugMsg ( library->fileName() + " does not have dataItem" );
continue;
}
QgsDataItem * item = dataItem ( path );
if ( item )
{
children.append( item );
}
}
}
return children;
}
bool QgsDirectoryItem::equal(const QgsDataItem *other)
{
//QgsDebugMsg ( mPath + " x " + other->mPath );
if ( typeid ( *this ) != typeid ( *other ) )
{
//QgsDebugMsg ( "different typeid" );
return false;
}
return ( mPath == other->mPath );
}
QWidget * QgsDirectoryItem::paramWidget()
{
return new QgsDirectoryParamWidget(mPath);
}
QgsDirectoryParamWidget::QgsDirectoryParamWidget(QString path, QWidget* parent)
: QTreeWidget(parent)
{
setRootIsDecorated(false);
// name, size, date, permissions, owner, group, type
setColumnCount (7);
QStringList labels;
labels << tr("Name") << tr("Size") << tr("Date") << tr("Permissions") << tr("Owner") << tr("Group") << tr("Type");
setHeaderLabels ( labels );
QStyle* style = QApplication::style();
QIcon iconDirectory = QIcon( style->standardPixmap( QStyle::SP_DirClosedIcon ) );
QIcon iconFile = QIcon( style->standardPixmap( QStyle::SP_FileIcon ) );
QIcon iconLink = QIcon( style->standardPixmap( QStyle::SP_FileLinkIcon ) ); // TODO: symlink to directory?
QList<QTreeWidgetItem *> items;
QDir dir(path);
QStringList entries = dir.entryList(QDir::AllEntries | QDir::NoDotAndDotDot, QDir::Name | QDir::IgnoreCase);
foreach (QString name, entries)
{
QFileInfo fi ( dir.absoluteFilePath(name) );
QStringList texts;
texts << name;
QString size;
if ( fi.size() > 1024 )
{
size = size.sprintf ( "%.1f KiB", fi.size()/1024.0 );
}
else if ( fi.size() > 1.048576e6 )
{
size = size.sprintf ( "%.1f MiB", fi.size()/1.048576e6 );
}
else
{
size = QString( "%1 B" ).arg( fi.size() );
}
texts << size;
texts << fi.lastModified().toString (Qt::SystemLocaleShortDate);
QString perm;
perm += fi.permission( QFile::ReadOwner ) ? 'r' : '-';
perm += fi.permission( QFile::WriteOwner ) ? 'w' : '-';
perm += fi.permission( QFile::ExeOwner ) ? 'x' : '-';
// QFile::ReadUser, QFile::WriteUser, QFile::ExeUser
perm += fi.permission( QFile::ReadGroup ) ? 'r' : '-';
perm += fi.permission( QFile::WriteGroup ) ? 'w' : '-';
perm += fi.permission( QFile::ExeGroup ) ? 'x' : '-';
perm += fi.permission( QFile::ReadOther ) ? 'r' : '-';
perm += fi.permission( QFile::WriteOther ) ? 'w' : '-';
perm += fi.permission( QFile::ExeOther ) ? 'x' : '-';
texts << perm;
texts << fi.owner();
texts << fi.group();
QString type;
QIcon icon;
if ( fi.isDir() )
{
type = tr ( "folder" );
icon = iconDirectory;
}
else if ( fi.isFile() )
{
type = tr ( "file" );
icon = iconFile;
}
else if ( fi.isSymLink() )
{
type = tr ( "link" );
icon = iconLink;
}
texts << type;
QTreeWidgetItem *item = new QTreeWidgetItem (texts);
item->setIcon(0, icon);
items << item;
}
addTopLevelItems(items);
// hide columns that are not requested
QSettings settings;
QList<QVariant> lst = settings.value("/dataitem/directoryHiddenColumns").toList();
foreach (QVariant colVariant, lst)
{
setColumnHidden( colVariant.toInt(), true );
}
}
void QgsDirectoryParamWidget::mousePressEvent(QMouseEvent* event)
{
if ( event->button() == Qt::RightButton )
{
// show the popup menu
QMenu popupMenu;
QStringList labels;
labels << tr("Name") << tr("Size") << tr("Date") << tr("Permissions") << tr("Owner") << tr("Group") << tr("Type");
for (int i = 0; i < labels.count(); i++)
{
QAction* action = popupMenu.addAction( labels[i], this, SLOT(showHideColumn()) );
action->setObjectName(QString::number(i));
action->setCheckable(true);
action->setChecked( !isColumnHidden(i) );
}
popupMenu.exec( event->globalPos() );
}
}
void QgsDirectoryParamWidget::showHideColumn()
{
QAction* action = qobject_cast<QAction*>(sender());
if (!action)
return; // something is wrong
int columnIndex = action->objectName().toInt();
setColumnHidden(columnIndex, !isColumnHidden(columnIndex));
// save in settings
QSettings settings;
QList<QVariant> lst;
for (int i = 0; i < columnCount(); i++)
{
if (isColumnHidden(i))
lst.append(QVariant(i));
}
settings.setValue("/dataitem/directoryHiddenColumns", lst);
}

197
src/core/qgsdataitem.h Normal file
View File

@ -0,0 +1,197 @@
/***************************************************************************
qgsdataitem.h - Items representing data
-------------------
begin : 2011-04-01
copyright : (C) 2011 Radim Blazek
email : radim dot blazek at gmail 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. *
* *
***************************************************************************/
/* $Id$ */
#ifndef QGSDATAITEM_H
#define QGSDATAITEM_H
#include <QIcon>
#include <QLibrary>
#include <QObject>
#include <QPixmap>
#include <QString>
#include <QVector>
#include <QTreeWidget>
#include "qgsmaplayer.h"
#include "qgscoordinatereferencesystem.h"
class QgsDataProvider;
/** base class for all items in the model */
class CORE_EXPORT QgsDataItem : public QObject
{
Q_OBJECT
public:
enum Type
{
Collection,
Directory,
Layer,
Vector,
Raster,
Point,
Line,
Polygon,
TableLayer,
Database,
Table
};
enum Capability
{
NoCapabilities = 0,
SetCrs = 1 //Can set CRS on layer or group of layers
};
QgsDataItem(QgsDataItem::Type type, QgsDataItem* parent, QString name, QString path);
virtual ~QgsDataItem() {}
virtual bool hasChildren();
virtual int rowCount();
virtual QIcon icon ();
void setParent ( QgsDataItem *parent ) { mParent = parent; }
QPixmap getThemePixmap( const QString theName );
// Sets info about layer which can be created for this item
// returns true if layer can be created
virtual bool layerInfo ( QgsMapLayer::LayerType & type,
QString & providerKey, QString & uri ) { return false; }
virtual void refresh();
// This will _write_ selected crs in data source
virtual bool setCrs ( QgsCoordinateReferenceSystem crs ) { return false; }
virtual Capability capabilities() { return NoCapabilities; }
// Create vector of children
virtual QVector<QgsDataItem*> createChildren();
// Populate children using children vector created by createChildren()
virtual void populate();
// Insert new child using alphabetical order based on mName, emits necessary signal to model before and after, sets parent and connects signals
// refresh - refresh populated item, emit signals to model
virtual void addChildItem ( QgsDataItem * child, bool refresh = false );
// remove and delete child item, signals to browser are emited
virtual void deleteChildItem ( QgsDataItem * child );
// Find child index in vector of items using '==' operator
int findItem ( QVector<QgsDataItem*> items, QgsDataItem * item );
Type mType;
QgsDataItem* mParent;
QVector<QgsDataItem*> mChildren; // easier to have it always
bool mPopulated;
QString mName;
// Are the data shared? Cannot be static because each child has different.
QIcon mDefaultIcon;
QIcon mIcon;
QString mPath; // it is also used to identify item in tree
virtual bool equal(const QgsDataItem *other) { return false; }
virtual QWidget * paramWidget() { return 0; }
public slots:
virtual void doubleClick();
void emitBeginInsertItems( QgsDataItem* parent, int first, int last );
void emitEndInsertItems();
void emitBeginRemoveItems( QgsDataItem* parent, int first, int last );
void emitEndRemoveItems();
signals:
void beginInsertItems( QgsDataItem* parent, int first, int last );
void endInsertItems();
void beginRemoveItems( QgsDataItem* parent, int first, int last );
void endRemoveItems();
};
/** Item that represents a layer that can be opened with one of the providers */
class CORE_EXPORT QgsLayerItem : public QgsDataItem
{
public:
QgsLayerItem(QgsDataItem* parent, QString name, QString path);
QgsLayerItem(QgsDataItem* parent, QgsDataItem::Type type, QString name, QString path, QString uri);
virtual QIcon icon ();
virtual bool equal(const QgsDataItem *other);
QString mProvider;
QString mUri;
};
/** A Collection: logical collection of layers or subcollections, e.g. GRASS location/mapset, database? wms source? */
class CORE_EXPORT QgsDataCollectionItem : public QgsDataItem
{
public:
QgsDataCollectionItem( QgsDataItem::Type type, QgsDataItem* parent, QString name, QString path =0);
~QgsDataCollectionItem();
void setPopulated() { mPopulated = true; }
void addChild( QgsDataItem *item ) { mChildren.append(item); }
};
/** A directory: contains subdirectories and layers */
class CORE_EXPORT QgsDirectoryItem : public QgsDataCollectionItem
{
public:
enum Column
{
Name,
Size,
Date,
Permissions,
Owner,
Group,
Type
};
QgsDirectoryItem(QgsDataItem* parent, QString name, QString path);
~QgsDirectoryItem();
QVector<QgsDataItem*> createChildren();
virtual bool equal(const QgsDataItem *other);
virtual QWidget * paramWidget();
static QVector<QgsDataProvider*> mProviders;
static QVector<QLibrary*> mLibraries;
};
class QgsDirectoryParamWidget : public QTreeWidget
{
Q_OBJECT
public:
QgsDirectoryParamWidget(QString path, QWidget* parent = NULL);
protected:
void mousePressEvent(QMouseEvent* event);
public slots:
void showHideColumn();
};
#endif // QGSDATAITEM_H

View File

@ -22,6 +22,8 @@
#include <QString>
#include <QStringList>
//#include "qgsdataitem.h"
class QgsRectangle;
class QgsCoordinateReferenceSystem;
@ -45,6 +47,17 @@ class CORE_EXPORT QgsDataProvider : public QObject
public:
Q_ENUMS( DataCapability )
enum DataCapability
{
NoDataCapabilities = 0,
File = 1,
Dir = 1 << 1,
Database = 1 << 2,
Net = 1 << 3 // Internet source
};
QgsDataProvider( QString const & uri = "" )
: mDataSourceURI( uri )
{}

View File

@ -909,3 +909,8 @@ void QgsMapLayer::clearCacheImage()
{
setCacheImage( 0 );
}
QString QgsMapLayer::metadata()
{
return QString();
}

View File

@ -332,6 +332,9 @@ class CORE_EXPORT QgsMapLayer : public QObject
* added in 1.5 */
void clearCacheImage();
/** \brief Obtain Metadata for this layer */
virtual QString metadata();
/** Time stamp of data source in the moment when data/metadata were loaded by provider */
virtual QDateTime timestamp() const { return QDateTime() ; }

View File

@ -41,6 +41,8 @@ typedef QString fileVectorFilters_t();
typedef QString databaseDrivers_t();
typedef QString directoryDrivers_t();
typedef QString protocolDrivers_t();
//typedef int dataCapabilities_t();
//typedef QgsDataItem * dataItem_t(QString);
QgsProviderRegistry *QgsProviderRegistry::_instance = 0;
@ -425,6 +427,64 @@ QgsDataProvider* QgsProviderRegistry::getProvider( QString const & providerKey,
} // QgsProviderRegistry::setDataProvider
// This should be QWidget, not QDialog
typedef QWidget * selectFactoryFunction_t( QWidget * parent, Qt::WFlags fl );
QWidget* QgsProviderRegistry::getSelectWidget( const QString & providerKey,
QWidget * parent, Qt::WFlags fl )
{
QLibrary *myLib = getLibrary( providerKey );
if ( !myLib ) return 0;
selectFactoryFunction_t * selectFactory =
( selectFactoryFunction_t * ) cast_to_fptr( myLib->resolve( "selectWidget" ) );
if ( !selectFactory ) return 0;
QWidget *widget = ( *selectFactory )( parent, fl );
return widget;
}
void * QgsProviderRegistry::getFunction( QString const & providerKey,
QString const & functionName )
{
QString lib = library( providerKey );
QLibrary* myLib = new QLibrary( lib );
QgsDebugMsg( "Library name is " + myLib->fileName() );
bool loaded = myLib->load();
if ( loaded )
{
void * ptr = myLib->resolve( functionName.toAscii().data() );
delete myLib;
return ptr;
}
delete myLib;
return 0;
}
QLibrary * QgsProviderRegistry::getLibrary( QString const & providerKey )
{
QString lib = library( providerKey );
QLibrary* myLib = new QLibrary( lib );
QgsDebugMsg( "Library name is " + myLib->fileName() );
bool loaded = myLib->load();
if ( loaded )
{
return myLib;
}
delete myLib;
return 0;
}
QString QgsProviderRegistry::fileVectorFilters() const
{
return mVectorFileFilters;

View File

@ -23,6 +23,7 @@
#include <map>
#include <QDir>
#include <QLibrary>
#include <QString>
@ -67,6 +68,19 @@ class CORE_EXPORT QgsProviderRegistry
QgsDataProvider * getProvider( const QString & providerKey,
const QString & dataSource );
QWidget * getSelectWidget ( const QString & providerKey,
QWidget * parent=0, Qt::WFlags fl=0 );
/** Get pointer to provider function
@param providerKey identificator of the provider
@param functionName name of function
@return pointer to function or NULL on error
*/
void * getFunction( const QString & providerKey,
const QString & functionName );
QLibrary * getLibrary ( const QString & providerKey );
/** Return list of available providers by their keys */
QStringList providerList() const;

View File

@ -0,0 +1,43 @@
#include "qgspythonrunner.h"
#include "qgslogger.h"
QgsPythonRunner* QgsPythonRunner::mInstance = NULL;
///////////////////////////
// static methods
bool QgsPythonRunner::isValid()
{
return mInstance != NULL;
}
bool QgsPythonRunner::run( QString command, QString messageOnError )
{
if ( mInstance )
{
return mInstance->runCommand( command, messageOnError );
}
else
{
QgsDebugMsg("Unable to run Python command: runner not available!");
return false;
}
}
void QgsPythonRunner::setInstance( QgsPythonRunner* runner )
{
delete mInstance;
mInstance = runner;
}
///////////////////////////
// non-static methods
QgsPythonRunner::QgsPythonRunner()
{
}
QgsPythonRunner::~QgsPythonRunner()
{
}

View File

@ -0,0 +1,41 @@
#ifndef QGSPYTHONRUNNER_H
#define QGSPYTHONRUNNER_H
#include <QString>
/**
Utility class for running python commands from various parts of QGIS.
There is no direct python support in the core library, so it is expected
that application with python support creates a subclass that implements
pure virtual function(s) during the initialization. The static methods
will then work as expected.
Added in QGIS v?
*/
class CORE_EXPORT QgsPythonRunner
{
public:
/** returns true if the runner has an instance
(and thus is able to run commands) */
static bool isValid();
/** execute a python statement */
static bool run( QString command, QString messageOnError = QString() );
/** assign an instance of python runner so that run() can be used.
This method should be called during app initialization.
Takes ownership of the object, deletes previous instance. */
static void setInstance( QgsPythonRunner* runner );
protected:
/** protected constructor: can be instantiated only from children */
QgsPythonRunner();
virtual ~QgsPythonRunner();
virtual bool runCommand( QString command, QString messageOnError = QString() ) = 0;
static QgsPythonRunner* mInstance;
};
#endif // QGSPYTHONRUNNER_H

View File

@ -5261,3 +5261,236 @@ void QgsVectorLayer::setDiagramLayerSettings( const QgsDiagramLayerSettings& s )
mDiagramLayerSettings = new QgsDiagramLayerSettings();
*mDiagramLayerSettings = s;
}
QString QgsVectorLayer::metadata()
{
QString myMetadata = "<html><body>";
myMetadata += "<table width=\"100%\">";
//-------------
myMetadata += "<tr class=\"glossy\"><td>";
myMetadata += tr( "General:" );
myMetadata += "</td></tr>";
// data comment
if ( !( dataComment().isEmpty() ) )
{
myMetadata += "<tr><td>";
myMetadata += tr( "Layer comment: %1" ).arg( dataComment() );
myMetadata += "</td></tr>";
}
//storage type
myMetadata += "<tr><td>";
myMetadata += tr( "Storage type of this layer: %1" ).arg( storageType() );
myMetadata += "</td></tr>";
// data source
myMetadata += "<tr><td>";
myMetadata += tr( "Source for this layer: %1" ).arg( publicSource() );
myMetadata += "</td></tr>";
//geom type
QGis::GeometryType type = geometryType();
if ( type < 0 || type > QGis::NoGeometry )
{
QgsDebugMsg( "Invalid vector type" );
}
else
{
QString typeString( QGis::qgisVectorGeometryType[geometryType()] );
myMetadata += "<tr><td>";
myMetadata += tr( "Geometry type of the features in this layer: %1" ).arg( typeString );
myMetadata += "</td></tr>";
}
//feature count
myMetadata += "<tr><td>";
myMetadata += tr( "The number of features in this layer: %1" ).arg( featureCount() );
myMetadata += "</td></tr>";
//capabilities
myMetadata += "<tr><td>";
myMetadata += tr( "Editing capabilities of this layer: %1" ).arg( capabilitiesString() );
myMetadata += "</td></tr>";
//-------------
QgsRectangle myExtent = extent();
myMetadata += "<tr class=\"glossy\"><td>";
myMetadata += tr( "Extents:" );
myMetadata += "</td></tr>";
//extents in layer cs TODO...maybe make a little nested table to improve layout...
myMetadata += "<tr><td>";
// Try to be a bit clever over what number format we use for the
// extents. Some people don't like it using scientific notation when the
// numbers get large, but for small numbers this is the more practical
// option (so we can't force the format to 'f' for all values).
// The scheme:
// - for all numbers with more than 5 digits, force non-scientific notation
// and 2 digits after the decimal point.
// - for all smaller numbers let the OS decide which format to use (it will
// generally use non-scientific unless the number gets much less than 1).
QString xMin, yMin, xMax, yMax;
double changeoverValue = 99999; // The 'largest' 5 digit number
if ( qAbs( myExtent.xMinimum() ) > changeoverValue )
{
xMin = QString( "%1" ).arg( myExtent.xMinimum(), 0, 'f', 2 );
}
else
{
xMin = QString( "%1" ).arg( myExtent.xMinimum() );
}
if ( qAbs( myExtent.yMinimum() ) > changeoverValue )
{
yMin = QString( "%1" ).arg( myExtent.yMinimum(), 0, 'f', 2 );
}
else
{
yMin = QString( "%1" ).arg( myExtent.yMinimum() );
}
if ( qAbs( myExtent.xMaximum() ) > changeoverValue )
{
xMax = QString( "%1" ).arg( myExtent.xMaximum(), 0, 'f', 2 );
}
else
{
xMax = QString( "%1" ).arg( myExtent.xMaximum() );
}
if ( qAbs( myExtent.yMaximum() ) > changeoverValue )
{
yMax = QString( "%1" ).arg( myExtent.yMaximum(), 0, 'f', 2 );
}
else
{
yMax = QString( "%1" ).arg( myExtent.yMaximum() );
}
myMetadata += tr( "In layer spatial reference system units : " )
+ tr( "xMin,yMin %1,%2 : xMax,yMax %3,%4" )
.arg( xMin ).arg( yMin ).arg( xMax ).arg( yMax );
myMetadata += "</td></tr>";
//extents in project cs
try
{
#if 0
// TODO: currently disabled, will revisit later [MD]
QgsRectangle myProjectedExtent = coordinateTransform->transformBoundingBox( extent() );
myMetadata += "<tr><td>";
myMetadata += tr( "In project spatial reference system units : " )
+ tr( "xMin,yMin %1,%2 : xMax,yMax %3,%4" )
.arg( myProjectedExtent.xMinimum() )
.arg( myProjectedExtent.yMinimum() )
.arg( myProjectedExtent.xMaximum() )
.arg( myProjectedExtent.yMaximum() );
myMetadata += "</td></tr>";
#endif
//
// Display layer spatial ref system
//
myMetadata += "<tr class=\"glossy\"><td>";
myMetadata += tr( "Layer Spatial Reference System:" );
myMetadata += "</td></tr>";
myMetadata += "<tr><td>";
myMetadata += crs().toProj4().replace( QRegExp( "\"" ), " \"" );
myMetadata += "</td></tr>";
//
// Display project (output) spatial ref system
//
#if 0
// TODO: disabled for now, will revisit later [MD]
myMetadata += "<tr><td bgcolor=\"gray\">";
myMetadata += tr( "Project (Output) Spatial Reference System:" );
myMetadata += "</td></tr>";
myMetadata += "<tr><td>";
myMetadata += coordinateTransform->destCRS().toProj4().replace( QRegExp( "\"" ), " \"" );
myMetadata += "</td></tr>";
#endif
}
catch ( QgsCsException &cse )
{
Q_UNUSED( cse );
QgsDebugMsg( cse.what() );
myMetadata += "<tr><td>";
myMetadata += tr( "In project spatial reference system units : " )
+ tr( "(Invalid transformation of layer extents)" );
myMetadata += "</td></tr>";
}
#if 0
//
// Add the info about each field in the attribute table
//
myMetadata += "<tr class=\"glossy\"><td>";
myMetadata += tr( "Attribute field info:" );
myMetadata += "</td></tr>";
myMetadata += "<tr><td>";
// Start a nested table in this trow
myMetadata += "<table width=\"100%\">";
myMetadata += "<tr><th>";
myMetadata += tr( "Field" );
myMetadata += "</th>";
myMetadata += "<th>";
myMetadata += tr( "Type" );
myMetadata += "</th>";
myMetadata += "<th>";
myMetadata += tr( "Length" );
myMetadata += "</th>";
myMetadata += "<th>";
myMetadata += tr( "Precision" );
myMetadata += "</th>";
myMetadata += "<th>";
myMetadata += tr( "Comment" );
myMetadata += "</th>";
//get info for each field by looping through them
const QgsFieldMap& myFields = pendingFields();
for ( QgsFieldMap::const_iterator it = myFields.begin(); it != myFields.end(); ++it )
{
const QgsField& myField = *it;
myMetadata += "<tr><td>";
myMetadata += myField.name();
myMetadata += "</td>";
myMetadata += "<td>";
myMetadata += myField.typeName();
myMetadata += "</td>";
myMetadata += "<td>";
myMetadata += QString( "%1" ).arg( myField.length() );
myMetadata += "</td>";
myMetadata += "<td>";
myMetadata += QString( "%1" ).arg( myField.precision() );
myMetadata += "</td>";
myMetadata += "<td>";
myMetadata += QString( "%1" ).arg( myField.comment() );
myMetadata += "</td></tr>";
}
//close field list
myMetadata += "</table>"; //end of nested table
#endif
myMetadata += "</td></tr>"; //end of stats container table row
//
// Close the table
//
myMetadata += "</table>";
myMetadata += "</body></html>";
return myMetadata;
}

View File

@ -688,6 +688,8 @@ class CORE_EXPORT QgsVectorLayer : public QgsMapLayer
@note added in 1.7 */
void checkJoinLayerRemove( QString theLayerId );
QString metadata();
signals:
/** This signal is emited when selection was changed */

View File

@ -22,6 +22,13 @@ symbology-ng/qgsvectorcolorbrewercolorrampv2dialog.cpp
symbology-ng/characterwidget.cpp
symbology-ng/qgsstylev2exportimportdialog.cpp
attributetable/qgsattributetablemodel.cpp
attributetable/qgsattributetablememorymodel.cpp
attributetable/qgsattributetableview.cpp
attributetable/qgsattributetablefiltermodel.cpp
attributetable/qgsattributetableidcolumnpair.cpp
attributetable/qgsattributetabledelegate.cpp
qgisgui.cpp
qgisinterface.cpp
qgsannotationitem.cpp
@ -38,6 +45,7 @@ qgsfiledropedit.cpp
qgsfieldvalidator.cpp
qgsformannotationitem.cpp
qgsgenericprojectionselector.cpp
qgsmanageconnectionsdialog.cpp
qgsmapcanvas.cpp
qgsmapcanvasitem.cpp
qgsmapcanvasmap.cpp
@ -49,6 +57,9 @@ qgsmaptoolemitpoint.cpp
qgsmaptoolpan.cpp
qgsmaptoolzoom.cpp
qgsmessageviewer.cpp
qgsnewhttpconnection.cpp
qgsnewvectorlayerdialog.cpp
qgsnumericsortlistviewitem.cpp
qgscredentialdialog.cpp
qgsprojectbadlayerguihandler.cpp
qgsprojectionselector.cpp
@ -83,6 +94,11 @@ symbology-ng/qgspenstylecombobox.h
symbology-ng/qgsbrushstylecombobox.h
symbology-ng/qgsstylev2exportimportdialog.h
attributetable/qgsattributetableview.h
attributetable/qgsattributetablemodel.h
attributetable/qgsattributetablememorymodel.h
attributetable/qgsattributetabledelegate.h
qgsattributeeditor.h
qgscomposerview.h
qgsdetaileditemdelegate.h
@ -93,10 +109,14 @@ qgsencodingfiledialog.h
qgsfieldvalidator.h
qgsformannotationitem.h
qgsgenericprojectionselector.h
qgsmanageconnectionsdialog.h
qgsmapcanvas.h
qgsmapoverviewcanvas.h
qgsmaptoolemitpoint.h
qgsmessageviewer.h
qgsnewhttpconnection.h
qgsnewvectorlayerdialog.h
qgsnumericsortlistviewitem.h
qgscredentialdialog.h
qgsprojectionselector.h
qgsquickprint.h
@ -211,6 +231,13 @@ qgssearchquerybuilder.h
qgsattributeeditor.h
qgsfieldvalidator.h
attributetable/qgsattributetablemodel.h
attributetable/qgsattributetablememorymodel.h
attributetable/qgsattributetableview.h
attributetable/qgsattributetablefiltermodel.h
attributetable/qgsattributetableidcolumnpair.h
attributetable/qgsattributetabledelegate.h
${CMAKE_CURRENT_BINARY_DIR}/../ui/ui_qgsdetaileditemwidgetbase.h
${CMAKE_CURRENT_BINARY_DIR}/../ui/ui_qgsgenericprojectionselectorbase.h
${CMAKE_CURRENT_BINARY_DIR}/../ui/ui_qgsmessageviewer.h

Some files were not shown because too many files have changed in this diff Show More