Skip to content

Commit 187f741

Browse files
committedNov 1, 2018
[FEATURE] Show QGIS style xml libraries in browser and support
drag and drop of style .xml files to main QGIS window Double clicking the databases or dragging them to QGIS triggers the import from style dialog with the corresponding input file already selected
1 parent 620643e commit 187f741

File tree

6 files changed

+210
-5
lines changed

6 files changed

+210
-5
lines changed
 

‎python/gui/auto_generated/symbology/qgsstyleexportimportdialog.sip.in

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,29 @@ class QgsStyleExportImportDialog : QDialog
1717
#include "qgsstyleexportimportdialog.h"
1818
%End
1919
public:
20+
2021
enum Mode
2122
{
2223
Export,
23-
Import
24+
Import,
2425
};
2526

2627
QgsStyleExportImportDialog( QgsStyle *style, QWidget *parent /TransferThis/ = 0, Mode mode = Export );
28+
%Docstring
29+
Constructor for QgsStyleExportImportDialog, with the specified ``parent`` widget.
30+
31+
Creates a dialog for importing symbols into the given ``style``, or exporting symbols from the ``style``.
32+
The ``mode`` argument dictates whether the dialog is to be used for exporting or importing symbols.
33+
%End
2734
~QgsStyleExportImportDialog();
2835

36+
void setImportFilePath( const QString &path );
37+
%Docstring
38+
Sets the initial ``path`` to use for importing files, when the dialog is in a Import mode.
39+
40+
.. versionadded:: 3.6
41+
%End
42+
2943
void selectSymbols( const QStringList &symbolNames );
3044
%Docstring
3145
selectSymbols select symbols by name

‎src/app/qgisapp.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1149,6 +1149,9 @@ QgisApp::QgisApp( QSplashScreen *splash, bool restorePlugins, bool skipVersionCh
11491149
registerCustomDropHandler( new QgsQlrDropHandler() );
11501150
QgsApplication::dataItemProviderRegistry()->addProvider( new QgsQptDataItemProvider() );
11511151
registerCustomDropHandler( new QgsQptDropHandler() );
1152+
QgsApplication::dataItemProviderRegistry()->addProvider( new QgsStyleXmlDataItemProvider() );
1153+
registerCustomDropHandler( new QgsStyleXmlDropHandler() );
1154+
11521155
mSplash->showMessage( tr( "Starting Python" ), Qt::AlignHCenter | Qt::AlignBottom );
11531156
qApp->processEvents();
11541157
loadPythonSupport();

‎src/app/qgsappbrowserproviders.cpp

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515

1616
#include "qgsappbrowserproviders.h"
1717
#include "qgisapp.h"
18+
#include "qgsstyleexportimportdialog.h"
19+
#include "qgsstyle.h"
1820
#include <QDesktopServices>
1921

2022
//
@@ -272,3 +274,128 @@ bool QgsPyDropHandler::handleFileDrop( const QString &file )
272274
}
273275
return false;
274276
}
277+
278+
279+
280+
281+
//
282+
// QgsStyleXmlDataItem
283+
//
284+
285+
QgsStyleXmlDataItem::QgsStyleXmlDataItem( QgsDataItem *parent, const QString &name, const QString &path )
286+
: QgsDataItem( QgsDataItem::Custom, parent, name, path )
287+
{
288+
setState( QgsDataItem::Populated ); // no children
289+
setIconName( QStringLiteral( "/mActionStyleManager.svg" ) );
290+
setToolTip( QStringLiteral( "<b>%1</b><br>%2" ).arg( tr( "QGIS style library" ), QDir::toNativeSeparators( path ) ) );
291+
}
292+
293+
bool QgsStyleXmlDataItem::hasDragEnabled() const
294+
{
295+
return true;
296+
}
297+
298+
QgsMimeDataUtils::Uri QgsStyleXmlDataItem::mimeUri() const
299+
{
300+
QgsMimeDataUtils::Uri u;
301+
u.layerType = QStringLiteral( "custom" );
302+
u.providerKey = QStringLiteral( "style_xml" );
303+
u.name = name();
304+
u.uri = path();
305+
return u;
306+
}
307+
308+
bool QgsStyleXmlDataItem::handleDoubleClick()
309+
{
310+
QgsStyleExportImportDialog dlg( QgsStyle::defaultStyle(), QgisApp::instance(), QgsStyleExportImportDialog::Import );
311+
dlg.setImportFilePath( mPath );
312+
dlg.exec();
313+
314+
return true;
315+
}
316+
317+
QList<QAction *> QgsStyleXmlDataItem::actions( QWidget *parent )
318+
{
319+
QAction *importAction = new QAction( tr( "&Import Style…" ), parent );
320+
const QString path = mPath;
321+
connect( importAction, &QAction::triggered, this, [path]
322+
{
323+
QgsStyleExportImportDialog dlg( QgsStyle::defaultStyle(), QgisApp::instance(), QgsStyleExportImportDialog::Import );
324+
dlg.setImportFilePath( path );
325+
dlg.exec();
326+
} );
327+
return QList<QAction *>() << importAction;
328+
}
329+
330+
//
331+
// QgsStyleXmlDataItemProvider
332+
//
333+
334+
335+
bool isStyleFile( const QString &path )
336+
{
337+
QFileInfo fileInfo( path );
338+
339+
if ( fileInfo.suffix().compare( QLatin1String( "xml" ), Qt::CaseInsensitive ) != 0 )
340+
return false;
341+
342+
// sniff the first line of the file to see if it's a style file
343+
if ( !QFile::exists( path ) )
344+
return false;
345+
346+
QFile inputFile( path );
347+
if ( !inputFile.open( QIODevice::ReadOnly ) )
348+
return false;
349+
350+
QTextStream stream( &inputFile );
351+
const QString line = stream.readLine();
352+
return line == QLatin1String( "<!DOCTYPE qgis_style>" );
353+
}
354+
355+
QString QgsStyleXmlDataItemProvider::name()
356+
{
357+
return QStringLiteral( "style_xml" );
358+
}
359+
360+
int QgsStyleXmlDataItemProvider::capabilities()
361+
{
362+
return QgsDataProvider::File;
363+
}
364+
365+
QgsDataItem *QgsStyleXmlDataItemProvider::createDataItem( const QString &path, QgsDataItem *parentItem )
366+
{
367+
if ( isStyleFile( path ) )
368+
{
369+
return new QgsStyleXmlDataItem( parentItem, QFileInfo( path ).fileName(), path );
370+
}
371+
return nullptr;
372+
}
373+
374+
//
375+
// QgsStyleXmlDropHandler
376+
//
377+
378+
QString QgsStyleXmlDropHandler::customUriProviderKey() const
379+
{
380+
return QStringLiteral( "style_xml" );
381+
}
382+
383+
void QgsStyleXmlDropHandler::handleCustomUriDrop( const QgsMimeDataUtils::Uri &uri ) const
384+
{
385+
QgsStyleExportImportDialog dlg( QgsStyle::defaultStyle(), QgisApp::instance(), QgsStyleExportImportDialog::Import );
386+
dlg.setImportFilePath( uri.uri );
387+
dlg.exec();
388+
}
389+
390+
bool QgsStyleXmlDropHandler::handleFileDrop( const QString &file )
391+
{
392+
if ( isStyleFile( file ) )
393+
{
394+
QgsStyleExportImportDialog dlg( QgsStyle::defaultStyle(), QgisApp::instance(), QgsStyleExportImportDialog::Import );
395+
dlg.setImportFilePath( file );
396+
dlg.exec();
397+
return true;
398+
}
399+
return false;
400+
}
401+

‎src/app/qgsappbrowserproviders.h

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,4 +146,47 @@ class QgsPyDropHandler : public QgsCustomDropHandler
146146
bool handleFileDrop( const QString &file ) override;
147147
};
148148

149+
150+
/**
151+
* Custom data item for XML style libraries.
152+
*/
153+
class QgsStyleXmlDataItem : public QgsDataItem
154+
{
155+
Q_OBJECT
156+
157+
public:
158+
159+
QgsStyleXmlDataItem( QgsDataItem *parent, const QString &name, const QString &path );
160+
bool hasDragEnabled() const override;
161+
QgsMimeDataUtils::Uri mimeUri() const override;
162+
bool handleDoubleClick() override;
163+
QList< QAction * > actions( QWidget *parent ) override;
164+
165+
};
166+
167+
/**
168+
* Data item provider for showing style XML libraries in the browser.
169+
*/
170+
class QgsStyleXmlDataItemProvider : public QgsDataItemProvider
171+
{
172+
public:
173+
QString name() override;
174+
int capabilities() override;
175+
QgsDataItem *createDataItem( const QString &path, QgsDataItem *parentItem ) override;
176+
};
177+
178+
/**
179+
* Handles drag and drop of style XML libraries to app.
180+
*/
181+
class QgsStyleXmlDropHandler : public QgsCustomDropHandler
182+
{
183+
Q_OBJECT
184+
185+
public:
186+
187+
QString customUriProviderKey() const override;
188+
void handleCustomUriDrop( const QgsMimeDataUtils::Uri &uri ) const override;
189+
bool handleFileDrop( const QString &file ) override;
190+
};
191+
149192
#endif // QGSAPPBROWSERPROVIDERS_H

‎src/gui/symbology/qgsstyleexportimportdialog.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -370,6 +370,11 @@ QgsStyleExportImportDialog::~QgsStyleExportImportDialog()
370370
delete mGroupSelectionDlg;
371371
}
372372

373+
void QgsStyleExportImportDialog::setImportFilePath( const QString &path )
374+
{
375+
mImportFileWidget->setFilePath( path );
376+
}
377+
373378
void QgsStyleExportImportDialog::selectAll()
374379
{
375380
listItems->selectAll();

‎src/gui/symbology/qgsstyleexportimportdialog.h

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,17 +44,30 @@ class GUI_EXPORT QgsStyleExportImportDialog : public QDialog, private Ui::QgsSty
4444
Q_OBJECT
4545

4646
public:
47+
48+
//! Dialog modes
4749
enum Mode
4850
{
49-
Export,
50-
Import
51+
Export, //!< Export existing symbols mode
52+
Import, //!< Import xml file mode
5153
};
5254

53-
// constructor
54-
// mode argument must be 0 for saving and 1 for loading
55+
/**
56+
* Constructor for QgsStyleExportImportDialog, with the specified \a parent widget.
57+
*
58+
* Creates a dialog for importing symbols into the given \a style, or exporting symbols from the \a style.
59+
* The \a mode argument dictates whether the dialog is to be used for exporting or importing symbols.
60+
*/
5561
QgsStyleExportImportDialog( QgsStyle *style, QWidget *parent SIP_TRANSFERTHIS = nullptr, Mode mode = Export );
5662
~QgsStyleExportImportDialog() override;
5763

64+
/**
65+
* Sets the initial \a path to use for importing files, when the dialog is in a Import mode.
66+
*
67+
* \since QGIS 3.6
68+
*/
69+
void setImportFilePath( const QString &path );
70+
5871
/**
5972
* \brief selectSymbols select symbols by name
6073
* \param symbolNames list of symbol names

0 commit comments

Comments
 (0)
Please sign in to comment.