How to use Share API in macOS and Qt Quick: Difference between revisions

From Qt Wiki
Jump to navigation Jump to search
No edit summary
No edit summary
Line 9: Line 9:
= Classes with Share API support. =
= Classes with Share API support. =


First you need to create class with all methods in Objective-C/C++ to use Share API. To do this you need follow a few steps:<br /># Create a new class and rename .cpp file to .mm.<br /># Add .h file to .pro of your project in section "OBJECTIVE_HEADERS" and .mm to "OBJECTIVE_SOURCES".<br /># Change .h file content to this code:<br /><code>#ifdef __cplusplus<br />extern "C" {<br />#endif
First you need to create class with all methods in Objective-C/C++ to use Share API. To do this you need follow a few steps:
# Create a new class and rename .cpp file to .mm.
# Add .h file to .pro of your project in section "OBJECTIVE_HEADERS" and .mm to "OBJECTIVE_SOURCES".
# Change .h file content to this code:
<code>#ifdef __cplusplus
extern "C" {
#endif


#import <Foundation/Foundation.h><br />#import <Social/Social.h>
#import <Foundation/Foundation.h>
#import <Social/Social.h>


/** </code>typedef QfSharePickerItemClicked<br /> * <code>param sharingService Selected type of sharing.<br /> * </code>author Andrew Shapovelov*/<br />typedef void(<sup>QfSharePickerItemClicked)(NSSharingService* sharingService);
/** </code>typedef QfSharePickerItemClicked
* <code>param sharingService Selected type of sharing.
* </code>author Andrew Shapovelov*/
typedef void(<sup>QfSharePickerItemClicked)(NSSharingService* sharingService);


<br />/** <code>class QfSharePicker<br /> * </code>brief Object to show share menu.<br /> * <code>author Andrew Shapovalov*/<br /></code>interface QfSharePicker : NSObject
<br />/** <code>brief Create a new object.<br /> * </code>param view View on what will show share menu.<br /> * <code>param frame Rect to show share window.<br /> * </code>param datas Datas items to share.<br /> * <code>param block Block of code to select item.<br /> * </code>author Andrew Shapovalov*/<br />- (instancetype)initWithView:(NSView*)view frame:(NSRect)frame datasArray:(NSArray*)datas onItemClicked:(QfSharePickerItemClicked)block;
<br /><code>end
<br />#ifdef __cplusplus<br />}<br />#endif<br /></code><br /># Change .mm file content to this code:<br /><code><br />#import "qfsharepicker.h"<br />#include <QtCore>
<br />/** </code>brief The private methods and properties of QfSharePicker class.<br /> * <code>author Andrew Shapovalov*/<br /></code>interface QfSharePicker () <NSSharingServicePickerDelegate, NSSharingServiceDelegate>
<br />/** Sharing service picker.*/<br /><code>property (nonatomic, retain) NSSharingServicePicker''' picker;
<br />/** Block of code to select item.*/<br /></code>property (nonatomic, copy) QfSharePickerItemClicked onItemClicked;
<br /><code>end


<br /></code>implementation QfSharePicker
/** <code>class QfSharePicker
<br />#pragma mark - Init methods
* </code>brief Object to show share menu.
<br />- (instancetype)initWithView:(NSView''')view frame:(NSRect)frame datasArray:(NSArray*)datas onItemClicked:(QfSharePickerItemClicked)block<br />{<br /> self = [super init];
* <code>author Andrew Shapovalov*/
<br /> if(self)<br /> {<br /> self.onItemClicked = block;<br /> self.picker = [[NSSharingServicePicker alloc] initWithItems: datas];<br /> self.picker.delegate = self;<br /> [self.picker showRelativeToRect:frame ofView:view preferredEdge:NSMinXEdge];<br /> }
</code>interface QfSharePicker : NSObject
<br /> return self;<br />}


<br />#pragma mark - NSSharingServicePickerDelegate methods
/** <code>brief Create a new object.
<br />- (void)sharingServicePicker:(NSSharingServicePicker ''')sharingServicePicker didChooseSharingService:(NSSharingService''')service<br />{<br /> if(self.picker == sharingServicePicker)<br /> {<br /> if(self.onItemClicked)<br /> {<br /> self.onItemClicked(service);<br /> }<br /> }<br />}
* </code>param view View on what will show share menu.
<br />- (id <NSSharingServiceDelegate>)sharingServicePicker:(NSSharingServicePicker ''')sharingServicePicker delegateForSharingService:(NSSharingService''')sharingService<br />{<br /> Q_UNUSED(sharingService);
* <code>param frame Rect to show share window.
<br /> if(self.picker == sharingServicePicker)<br /> {<br /> }
* </code>param datas Datas items to share.
<br /> return self;<br />}
* <code>param block Block of code to select item.
<br />#pragma mark - NSSharingServiceDelegate methods
* </code>author Andrew Shapovalov*/
<br />- (void)sharingService:(NSSharingService ''')sharingService willShareItems:(NSArray''')items<br />{<br /> Q_UNUSED(sharingService);<br /> Q_UNUSED(items);
- (instancetype)initWithView:(NSView*)view frame:(NSRect)frame datasArray:(NSArray*)datas onItemClicked:(QfSharePickerItemClicked)block;
<br /> //Some code here<br />}
<br />- (void)sharingService:(NSSharingService ''')sharingService didFailToShareItems:(NSArray''')items error:(NSError ''')error<br />{<br /> Q_UNUSED(sharingService);<br /> Q_UNUSED(items);<br /> Q_UNUSED(error);
<br /> //Some code here<br />}
<br />- (void)sharingService:(NSSharingService''')sharingService didShareItems:(NSArray ''')items<br />{<br /> Q_UNUSED(sharingService);<br /> Q_UNUSED(items);
<br /> //Some code here<br />}
<br />#pragma mark - Clear memory
<br />- (void)dealloc<br />{<br /> [super dealloc];
<br /> [self.picker autorelease];<br /> [self.onItemClicked release];<br /> self.onItemClicked = nil;<br />}
<br /><code>end<br /></code><br />p. More information you can find in official Apple "documentation":https://developer.apple.com/library/mac/DOCUMENTATION/AppKit/Reference/NSSharingServicePicker_Class/index.html. And you need to see information about class "NSSharingServicePickerDelegate":https://developer.apple.com/library/mac/DOCUMENTATION/AppKit/Reference/NSSharingServicePickerDelegate_Protocol/index.html#//apple_ref/occ/intf/NSSharingServicePickerDelegate.
<br />h1. Create QtQuick Item to use Share API from App.
<br />p. Second class which you need to create is a class to call from C+''. This class will call Objective-C/C. To do this you need follow a few steps:<br /># Create a new C''+ class.<br /># Rename .cpp file to .mm and added it to "OBJECTIVE_SOURCES".<br /># Change .h file content to code:<br /><code>
<br />#include <QtCore><br />#include <QtQuick>
<br />/'''* </code>class QfShareItem<br /> * <code>brief Manager to use share logic.<br /> * </code>author Andrew Shapovalov*/<br />class QfShareItem : public QQuickPaintedItem<br />{<br /> Q_OBJECT<br /> Q_PROPERTY(QString shareString READ getShareString WRITE setShareString NOTIFY shareStringChanged)<br /> Q_PROPERTY(QUrl shareUrl READ getShareUrl WRITE setShareUrl NOTIFY shareUrlChanged)
<br /> private:<br /> /** The share string info.*/<br /> QString m_shareString;
<br /> /'''* The share link.*/<br /> QUrl m_shareUrl;
<br /> /'''* <code>brief Strip all HTML tags from string.<br /> * </code>param body The source string.<br /> * <code>return Plain text.<br /> * </code>author Andrew Shapovalov*/<br /> QString stripHTMLTags(QString body);
<br /> /** <code>brief Works with all applications events.<br /> * </code>param obj The object which call event.<br /> * <code>param event The event of call.<br /> * </code>author Andrew Shapovalov*/<br /> bool eventFilter(QObject* obj, QEvent* event);
<br /> /** <code>brief Share current content.<br /> * </code>author Andrew Shapovalov*/<br /> void shareCurrentContent();
<br /> public:<br /> /** <code>brief Create a new object.<br /> * </code>param parent Parent object.<br /> * <code>author Andrew Shapovalov*/<br /> explicit QfShareItem(QQuickPaintedItem '''parent = 0);
<br /> //Others<br /> /'''* </code>brief Called when current object will redrawing.<br /> * <code>param painter The object for draw data.<br /> * </code>author Andrew Shapovalov*/<br /> void paint(QPainter '''painter);
<br /> //Getters<br /> /'''* <code>brief Get share content string.<br /> * </code>return Share string content.<br /> * <code>author Andrew Shapovalov*/<br /> inline QString getShareString(){return m_shareString;}
<br /> /** </code>brief Get share url.<br /> * <code>return Share url.<br /> * </code>author Andrew Shapovalov*/<br /> inline QUrl getShareUrl(){return m_shareUrl;}
<br /> //Setters<br /> /** <code>brief Set share content string.<br /> * </code>param value Share string content.<br /> * <code>author Andrew Shapovalov*/<br /> inline void setShareString(QString value){m_shareString = value; emit shareStringChanged(m_shareString);}
<br /> /** </code>brief Set share url.<br /> * <code>param value Share url.<br /> * </code>author Andrew Shapovalov*/<br /> inline void setShareUrl(QUrl value){m_shareUrl = value; emit shareUrlChanged(m_shareUrl);}
<br /> /** <code>brief Share content and url.<br /> * </code>param text The text of share.<br /> * <code>param url The url to share.<br /> * </code>author Andrew Shapovalov*/<br /> Q_INVOKABLE void shareContent(QString text = QString(), QUrl url = QUrl());
<br /> signals:<br /> /** <code>brief Called when share content string was changed.<br /> * </code>param value Share string content.<br /> * <code>author Andrew Shapovalov*/<br /> void shareStringChanged(QString value);
<br /> /** </code>brief Called when share url was changed.<br /> * <code>param value Share url.<br /> * </code>author Andrew Shapovalov*/<br /> void shareUrlChanged(QUrl value);
<br /> /** <code>brief Called when user select share service.<br /> * </code>param serviceName The name of selected service.<br /> * <code>author Andrew Shapovalov*/<br /> void selectedService(QString serviceName);
<br /> public slots:<br />};<br /></code><br /># Change .mm file content to code:<br /><code><br />#include "qfshareitem.h"<br />#include "qfsharepicker.h"
<br />QString QfShareItem::stripHTMLTags(QString body)<br />{<br /> body.replace("<br>","");<br /> body.replace("</br>","");<br /> body.replace("</p>","");<br /> body.replace("</td>","");<br /> body.remove(QRegExp("<head&amp;amp;gt;(.''')</head&amp;amp;gt;"));<br /> body.remove(QRegExp("<form(.''')</form>"));<br /> body.remove(QRegExp( "<(.)[</sup>>]'''>"));
<br /> return body.trimmed();<br />}
<br />bool QfShareItem::eventFilter(QObject''' obj, QEvent* event)<br />{<br /> if(obj == this)<br /> {<br /> if(parentItem())<br /> {<br /> return QObject::eventFilter(parentItem(), event);<br /> }<br /> }


return QObject::eventFilter(obj, event);<br />}
<code>end


void QfShareItem::shareCurrentContent()<br />{<br /> QQuickItem* parentItem = this->parentItem();<br /> if(!m_shareString.isEmpty() &amp;&amp; parentItem)<br /> {<br /> QRectF rect = parentItem->mapRectToItem(NULL, parentItem->boundingRect());<br /> NSView* view = reinterpret_cast<NSView *>(parentItem->window()->winId());<br /> NSRect frame = NSMakeRect(rect.x(), rect.y(), rect.width(), rect.height());
#ifdef __cplusplus
<br /> m_shareString = m_shareString.replace("<style type=quot;text/cssquot;>a {color:#44a51c;text-decoration:none;}</style&amp;amp;gt;", "");<br /> QString content = stripHTMLTags(m_shareString).trimmed();<br /> NSMutableArray* datas = [NSMutableArray arrayWithObject: content.toNSString()];<br /> if(!m_shareUrl.isEmpty())<br /> {<br /> NSURL* url = [NSURL URLWithString: m_shareUrl.toString().toNSString()];<br /> if(url)<br /> {<br /> [datas addObject: url];<br /> }<br /> }<br /> QfSharePicker* sharePicker = [[QfSharePicker alloc] initWithView:view frame:frame datasArray:datas onItemClicked:nil];<br /> [sharePicker autorelease];<br /> }<br />}
}
<br />QfShareItem::QfShareItem(QQuickPaintedItem '''parent) :<br /> QQuickPaintedItem(parent)<br />{<br /> m_shareString.clear();<br /> m_shareUrl.clear();
#endif
<br /> connect(this, &amp;QQuickPaintedItem::parentChanged, [this](QQuickItem''' newParent){
</code>
<br /> if(newParent)<br /> {<br /> newParent->setFiltersChildMouseEvents(true);<br /> }<br /> });<br /> this->installEventFilter(this);
# Change .mm file content to this code:
<code>
#import "qfsharepicker.h"
#include <QtCore>


setFlag(QQuickPaintedItem::ItemHasContents, true);<br /> setFlag(QQuickPaintedItem::ItemClipsChildrenToShape, true);<br /> setFlag(QQuickPaintedItem::ItemAcceptsDrops, true);<br /> setRenderTarget(QQuickPaintedItem::InvertedYFramebufferObject);<br />}
/** </code>brief The private methods and properties of QfSharePicker class.
* <code>author Andrew Shapovalov*/
</code>interface QfSharePicker () <NSSharingServicePickerDelegate, NSSharingServiceDelegate>


void QfShareItem::paint(QPainter *painter)<br />{<br /> try<br /> {<br /> Q_UNUSED(painter);<br /> }<br /> catch(std::exception&amp;amp; exception)<br /> {<br /> qDebug()<<"exception: "<<exception.what();<br /> }<br />}
/** Sharing service picker.*/
<code>property (nonatomic, retain) NSSharingServicePicker''' picker;


void QfShareItem::shareContent(QString text, QUrl url)<br />{<br /> if(!text.isEmpty())<br /> {<br /> m_shareString = text;<br /> }
/** Block of code to select item.*/
</code>property (nonatomic, copy) QfSharePickerItemClicked onItemClicked;


if(!url.isEmpty())<br /> {<br /> m_shareUrl = url;<br /> }
<code>end


shareCurrentContent();<br />}<br /></code><br /># Register new type to use in QML.<br /><code><br />qmlRegisterType<YourShareItem>(uri, 1, 1, "YourShareItem");<br /></code>
 
</code>implementation QfSharePicker
 
#pragma mark - Init methods
 
- (instancetype)initWithView:(NSView''')view frame:(NSRect)frame datasArray:(NSArray*)datas onItemClicked:(QfSharePickerItemClicked)block
{
self = [super init];
 
if(self)
{
self.onItemClicked = block;
self.picker = [[NSSharingServicePicker alloc] initWithItems: datas];
self.picker.delegate = self;
[self.picker showRelativeToRect:frame ofView:view preferredEdge:NSMinXEdge];
}
 
return self;
}
 
 
#pragma mark - NSSharingServicePickerDelegate methods
 
- (void)sharingServicePicker:(NSSharingServicePicker ''')sharingServicePicker didChooseSharingService:(NSSharingService''')service
{
if(self.picker == sharingServicePicker)
{
if(self.onItemClicked)
{
self.onItemClicked(service);
}
}
}
 
- (id <NSSharingServiceDelegate>)sharingServicePicker:(NSSharingServicePicker ''')sharingServicePicker delegateForSharingService:(NSSharingService''')sharingService
{
Q_UNUSED(sharingService);
 
if(self.picker == sharingServicePicker)
{
}
 
return self;
}
 
#pragma mark - NSSharingServiceDelegate methods
 
- (void)sharingService:(NSSharingService ''')sharingService willShareItems:(NSArray''')items
{
Q_UNUSED(sharingService);
Q_UNUSED(items);
 
//Some code here
}
 
- (void)sharingService:(NSSharingService ''')sharingService didFailToShareItems:(NSArray''')items error:(NSError ''')error
{
Q_UNUSED(sharingService);
Q_UNUSED(items);
Q_UNUSED(error);
 
//Some code here
}
 
- (void)sharingService:(NSSharingService''')sharingService didShareItems:(NSArray ''')items
{
Q_UNUSED(sharingService);
Q_UNUSED(items);
 
//Some code here
}
 
#pragma mark - Clear memory
 
- (void)dealloc
{
[super dealloc];
 
[self.picker autorelease];
[self.onItemClicked release];
self.onItemClicked = nil;
}
 
<code>end
</code>
p. More information you can find in official Apple "documentation":https://developer.apple.com/library/mac/DOCUMENTATION/AppKit/Reference/NSSharingServicePicker_Class/index.html. And you need to see information about class "NSSharingServicePickerDelegate":https://developer.apple.com/library/mac/DOCUMENTATION/AppKit/Reference/NSSharingServicePickerDelegate_Protocol/index.html#//apple_ref/occ/intf/NSSharingServicePickerDelegate.
 
h1. Create QtQuick Item to use Share API from App.
 
p. Second class which you need to create is a class to call from C+''. This class will call Objective-C/C. To do this you need follow a few steps:
# Create a new C''+ class.
# Rename .cpp file to .mm and added it to "OBJECTIVE_SOURCES".
# Change .h file content to code:
<code>
 
#include <QtCore>
#include <QtQuick>
 
/'''* </code>class QfShareItem
* <code>brief Manager to use share logic.
* </code>author Andrew Shapovalov*/
class QfShareItem : public QQuickPaintedItem
{
Q_OBJECT
Q_PROPERTY(QString shareString READ getShareString WRITE setShareString NOTIFY shareStringChanged)
Q_PROPERTY(QUrl shareUrl READ getShareUrl WRITE setShareUrl NOTIFY shareUrlChanged)
 
private:
/** The share string info.*/
QString m_shareString;
 
/'''* The share link.*/
QUrl m_shareUrl;
 
/'''* <code>brief Strip all HTML tags from string.
* </code>param body The source string.
* <code>return Plain text.
* </code>author Andrew Shapovalov*/
QString stripHTMLTags(QString body);
 
/** <code>brief Works with all applications events.
* </code>param obj The object which call event.
* <code>param event The event of call.
* </code>author Andrew Shapovalov*/
bool eventFilter(QObject* obj, QEvent* event);
 
/** <code>brief Share current content.
* </code>author Andrew Shapovalov*/
void shareCurrentContent();
 
public:
/** <code>brief Create a new object.
* </code>param parent Parent object.
* <code>author Andrew Shapovalov*/
explicit QfShareItem(QQuickPaintedItem '''parent = 0);
 
//Others
/'''* </code>brief Called when current object will redrawing.
* <code>param painter The object for draw data.
* </code>author Andrew Shapovalov*/
void paint(QPainter '''painter);
 
//Getters
/'''* <code>brief Get share content string.
* </code>return Share string content.
* <code>author Andrew Shapovalov*/
inline QString getShareString(){return m_shareString;}
 
/** </code>brief Get share url.
* <code>return Share url.
* </code>author Andrew Shapovalov*/
inline QUrl getShareUrl(){return m_shareUrl;}
 
//Setters
/** <code>brief Set share content string.
* </code>param value Share string content.
* <code>author Andrew Shapovalov*/
inline void setShareString(QString value){m_shareString = value; emit shareStringChanged(m_shareString);}
 
/** </code>brief Set share url.
* <code>param value Share url.
* </code>author Andrew Shapovalov*/
inline void setShareUrl(QUrl value){m_shareUrl = value; emit shareUrlChanged(m_shareUrl);}
 
/** <code>brief Share content and url.
* </code>param text The text of share.
* <code>param url The url to share.
* </code>author Andrew Shapovalov*/
Q_INVOKABLE void shareContent(QString text = QString(), QUrl url = QUrl());
 
signals:
/** <code>brief Called when share content string was changed.
* </code>param value Share string content.
* <code>author Andrew Shapovalov*/
void shareStringChanged(QString value);
 
/** </code>brief Called when share url was changed.
* <code>param value Share url.
* </code>author Andrew Shapovalov*/
void shareUrlChanged(QUrl value);
 
/** <code>brief Called when user select share service.
* </code>param serviceName The name of selected service.
* <code>author Andrew Shapovalov*/
void selectedService(QString serviceName);
 
public slots:
};
</code>
# Change .mm file content to code:
<code>
#include "qfshareitem.h"
#include "qfsharepicker.h"
 
QString QfShareItem::stripHTMLTags(QString body)
{
body.replace("<br>","");
body.replace("</br>","");
body.replace("</p>","");
body.replace("</td>","");
body.remove(QRegExp("<head&amp;amp;gt;(.''')</head&amp;amp;gt;"));
body.remove(QRegExp("<form(.''')</form>"));
body.remove(QRegExp( "<(.)[</sup>>]'''>"));
 
return body.trimmed();
}
 
bool QfShareItem::eventFilter(QObject''' obj, QEvent* event)
{
if(obj == this)
{
if(parentItem())
{
return QObject::eventFilter(parentItem(), event);
}
}
 
return QObject::eventFilter(obj, event);
}
 
void QfShareItem::shareCurrentContent()
{
QQuickItem* parentItem = this->parentItem();
if(!m_shareString.isEmpty() &amp;&amp; parentItem)
{
QRectF rect = parentItem->mapRectToItem(NULL, parentItem->boundingRect());
NSView* view = reinterpret_cast<NSView *>(parentItem->window()->winId());
NSRect frame = NSMakeRect(rect.x(), rect.y(), rect.width(), rect.height());
 
m_shareString = m_shareString.replace("<style type=quot;text/cssquot;>a {color:#44a51c;text-decoration:none;}</style&amp;amp;gt;", "");
QString content = stripHTMLTags(m_shareString).trimmed();
NSMutableArray* datas = [NSMutableArray arrayWithObject: content.toNSString()];
if(!m_shareUrl.isEmpty())
{
NSURL* url = [NSURL URLWithString: m_shareUrl.toString().toNSString()];
if(url)
{
[datas addObject: url];
}
}
QfSharePicker* sharePicker = [[QfSharePicker alloc] initWithView:view frame:frame datasArray:datas onItemClicked:nil];
[sharePicker autorelease];
}
}
 
QfShareItem::QfShareItem(QQuickPaintedItem '''parent) :
QQuickPaintedItem(parent)
{
m_shareString.clear();
m_shareUrl.clear();
 
connect(this, &amp;QQuickPaintedItem::parentChanged, [this](QQuickItem''' newParent){
 
if(newParent)
{
newParent->setFiltersChildMouseEvents(true);
}
});
this->installEventFilter(this);
 
setFlag(QQuickPaintedItem::ItemHasContents, true);
setFlag(QQuickPaintedItem::ItemClipsChildrenToShape, true);
setFlag(QQuickPaintedItem::ItemAcceptsDrops, true);
setRenderTarget(QQuickPaintedItem::InvertedYFramebufferObject);
}
 
void QfShareItem::paint(QPainter *painter)
{
try
{
Q_UNUSED(painter);
}
catch(std::exception&amp;amp; exception)
{
qDebug()<<"exception: "<<exception.what();
}
}
 
void QfShareItem::shareContent(QString text, QUrl url)
{
if(!text.isEmpty())
{
m_shareString = text;
}
 
if(!url.isEmpty())
{
m_shareUrl = url;
}
 
shareCurrentContent();
}
</code>
# Register new type to use in QML.
<code>
qmlRegisterType<YourShareItem>(uri, 1, 1, "YourShareItem");
</code>


= How to use in QML. =
= How to use in QML. =


Import the new type to your QML file where you need to use share logic and add this code:<br /><code><br />Button {<br /> id: btnLink<br /> width: 22<br /> height: 22
Import the new type to your QML file where you need to use share logic and add this code:
<code>
Button {
id: btnLink
width: 22
height: 22


onClicked: {<br /> share.shareContent();<br /> }
onClicked: {
share.shareContent();
}


QfShareItem {<br /> id: share<br /> anchors.fill: btnLink<br /> shareUrl: userPanelView.shareUrl<br /> }<br />}<br /></code>
QfShareItem {
id: share
anchors.fill: btnLink
shareUrl: userPanelView.shareUrl
}
}
</code>


= Summary =
= Summary =

Revision as of 11:21, 25 February 2015

[toc align_right="yes" depth="2"]

Hi everyone!

In this article I've tried to explain how to use Mac OS X Share API in your Qt Quick app. Share API was implemented in Mac OS 10.10 (Yosemite).

As you know all frameworks in OS X which you could use in your application created with Objective-C/C+. That's why you can't use framework in your C+ classes. You need to rename your .cpp file to .mm and then you can call Objective-C code. But sometimes you need to call methods with arguments with Objective-C. As you know in .h file you can't call Objective-C code. You must create Objective-C class which will call all needed methods to work with target framework.

Classes with Share API support.

First you need to create class with all methods in Objective-C/C++ to use Share API. To do this you need follow a few steps:

  1. Create a new class and rename .cpp file to .mm.
  2. Add .h file to .pro of your project in section "OBJECTIVE_HEADERS" and .mm to "OBJECTIVE_SOURCES".
  3. Change .h file content to this code:
#ifdef __cplusplus
extern "C" {
#endif

#import <Foundation/Foundation.h>
#import <Social/Social.h>

/**

typedef QfSharePickerItemClicked *

param sharingService Selected type of sharing.
 *

author Andrew Shapovelov*/

typedef void(QfSharePickerItemClicked)(NSSharingService* sharingService);


/**

class QfSharePicker
 *

brief Object to show share menu. *

author Andrew Shapovalov*/

interface QfSharePicker : NSObject /**

brief Create a new object.
 *

param view View on what will show share menu. *

param frame Rect to show share window.
 *

param datas Datas items to share. *

param block Block of code to select item.
 *

author Andrew Shapovalov*/

- (instancetype)initWithView:(NSView*)view frame:(NSRect)frame datasArray:(NSArray*)datas onItemClicked:(QfSharePickerItemClicked)block;

end

#ifdef __cplusplus
}
#endif
  1. Change .mm file content to this code:
#import "qfsharepicker.h"
#include <QtCore>

/**

brief The private methods and properties of QfSharePicker class. *

author Andrew Shapovalov*/

interface QfSharePicker () <NSSharingServicePickerDelegate, NSSharingServiceDelegate>

/** Sharing service picker.*/

property (nonatomic, retain) NSSharingServicePicker''' picker;

/** Block of code to select item.*/

property (nonatomic, copy) QfSharePickerItemClicked onItemClicked;

end

implementation QfSharePicker

  1. pragma mark - Init methods

- (instancetype)initWithView:(NSView)view frame:(NSRect)frame datasArray:(NSArray*)datas onItemClicked:(QfSharePickerItemClicked)block {

self = [super init];
if(self)
{
self.onItemClicked = block;
self.picker = [[NSSharingServicePicker alloc] initWithItems: datas];
self.picker.delegate = self;
[self.picker showRelativeToRect:frame ofView:view preferredEdge:NSMinXEdge];
}
return self;

}


  1. pragma mark - NSSharingServicePickerDelegate methods

- (void)sharingServicePicker:(NSSharingServicePicker )sharingServicePicker didChooseSharingService:(NSSharingService)service {

if(self.picker == sharingServicePicker)
{
if(self.onItemClicked)
{
self.onItemClicked(service);
}
}

}

- (id <NSSharingServiceDelegate>)sharingServicePicker:(NSSharingServicePicker )sharingServicePicker delegateForSharingService:(NSSharingService)sharingService {

Q_UNUSED(sharingService);
if(self.picker == sharingServicePicker)
{
}
return self;

}

  1. pragma mark - NSSharingServiceDelegate methods

- (void)sharingService:(NSSharingService )sharingService willShareItems:(NSArray)items {

Q_UNUSED(sharingService);
Q_UNUSED(items);
//Some code here

}

- (void)sharingService:(NSSharingService )sharingService didFailToShareItems:(NSArray)items error:(NSError )error {

Q_UNUSED(sharingService);
Q_UNUSED(items);
Q_UNUSED(error);
//Some code here

}

- (void)sharingService:(NSSharingService)sharingService didShareItems:(NSArray )items {

Q_UNUSED(sharingService);
Q_UNUSED(items);
//Some code here

}

  1. pragma mark - Clear memory

- (void)dealloc {

[super dealloc];
[self.picker autorelease];
[self.onItemClicked release];
self.onItemClicked = nil;

}

end

p. More information you can find in official Apple "documentation":https://developer.apple.com/library/mac/DOCUMENTATION/AppKit/Reference/NSSharingServicePicker_Class/index.html. And you need to see information about class "NSSharingServicePickerDelegate":https://developer.apple.com/library/mac/DOCUMENTATION/AppKit/Reference/NSSharingServicePickerDelegate_Protocol/index.html#//apple_ref/occ/intf/NSSharingServicePickerDelegate.

h1. Create QtQuick Item to use Share API from App.

p. Second class which you need to create is a class to call from C+. This class will call Objective-C/C. To do this you need follow a few steps:

  1. Create a new C+ class.
  2. Rename .cpp file to .mm and added it to "OBJECTIVE_SOURCES".
  3. Change .h file content to code:
#include <QtCore>
#include <QtQuick>

/'''*

class QfShareItem *

brief Manager to use share logic.
 *

author Andrew Shapovalov*/

class QfShareItem : public QQuickPaintedItem {

Q_OBJECT
Q_PROPERTY(QString shareString READ getShareString WRITE setShareString NOTIFY shareStringChanged)
Q_PROPERTY(QUrl shareUrl READ getShareUrl WRITE setShareUrl NOTIFY shareUrlChanged)
private:
/** The share string info.*/
QString m_shareString;
/* The share link.*/
QUrl m_shareUrl;

/*

brief Strip all HTML tags from string.
 *

param body The source string. *

return Plain text.
 *

author Andrew Shapovalov*/

QString stripHTMLTags(QString body);

/**

brief Works with all applications events.
 *

param obj The object which call event. *

param event The event of call.
 *

author Andrew Shapovalov*/

bool eventFilter(QObject* obj, QEvent* event);

/**

brief Share current content.
 *

author Andrew Shapovalov*/

void shareCurrentContent();
public:

/**

brief Create a new object.
 *

param parent Parent object. *

author Andrew Shapovalov*/
 explicit QfShareItem(QQuickPaintedItem '''parent = 0);

 //Others
 /'''*

brief Called when current object will redrawing. *

param painter The object for draw data.
 *

author Andrew Shapovalov*/

void paint(QPainter painter);
//Getters

/*

brief Get share content string.
 *

return Share string content. *

author Andrew Shapovalov*/
 inline QString getShareString(){return m_shareString;}

 /**

brief Get share url. *

return Share url.
 *

author Andrew Shapovalov*/

inline QUrl getShareUrl(){return m_shareUrl;}
//Setters

/**

brief Set share content string.
 *

param value Share string content. *

author Andrew Shapovalov*/
 inline void setShareString(QString value){m_shareString = value; emit shareStringChanged(m_shareString);}

 /**

brief Set share url. *

param value Share url.
 *

author Andrew Shapovalov*/

inline void setShareUrl(QUrl value){m_shareUrl = value; emit shareUrlChanged(m_shareUrl);}

/**

brief Share content and url.
 *

param text The text of share. *

param url The url to share.
 *

author Andrew Shapovalov*/

Q_INVOKABLE void shareContent(QString text = QString(), QUrl url = QUrl());
signals:

/**

brief Called when share content string was changed.
 *

param value Share string content. *

author Andrew Shapovalov*/
 void shareStringChanged(QString value);

 /**

brief Called when share url was changed. *

param value Share url.
 *

author Andrew Shapovalov*/

void shareUrlChanged(QUrl value);

/**

brief Called when user select share service.
 *

param serviceName The name of selected service. *

author Andrew Shapovalov*/
 void selectedService(QString serviceName);

 public slots:
};
  1. Change .mm file content to code:
#include "qfshareitem.h"
#include "qfsharepicker.h"

QString QfShareItem::stripHTMLTags(QString body)
{
 body.replace("<br>","");
 body.replace("</br>","");
 body.replace("</p>","");
 body.replace("</td>","");
 body.remove(QRegExp("<head&amp;amp;gt;(.''')</head&amp;amp;gt;"));
 body.remove(QRegExp("<form(.''')</form>"));
 body.remove(QRegExp( "<(.)[</sup>>]'''>"));

 return body.trimmed();
}

bool QfShareItem::eventFilter(QObject''' obj, QEvent* event)
{
 if(obj == this)
 {
 if(parentItem())
 {
 return QObject::eventFilter(parentItem(), event);
 }
 }

return QObject::eventFilter(obj, event);
}

void QfShareItem::shareCurrentContent()
{
 QQuickItem* parentItem = this->parentItem();
 if(!m_shareString.isEmpty() &amp;&amp; parentItem)
 {
 QRectF rect = parentItem->mapRectToItem(NULL, parentItem->boundingRect());
 NSView* view = reinterpret_cast<NSView *>(parentItem->window()->winId());
 NSRect frame = NSMakeRect(rect.x(), rect.y(), rect.width(), rect.height());

 m_shareString = m_shareString.replace("<style type=quot;text/cssquot;>a {color:#44a51c;text-decoration:none;}</style&amp;amp;gt;", "");
 QString content = stripHTMLTags(m_shareString).trimmed();
 NSMutableArray* datas = [NSMutableArray arrayWithObject: content.toNSString()];
 if(!m_shareUrl.isEmpty())
 {
 NSURL* url = [NSURL URLWithString: m_shareUrl.toString().toNSString()];
 if(url)
 {
 [datas addObject: url];
 }
 }
 QfSharePicker* sharePicker = [[QfSharePicker alloc] initWithView:view frame:frame datasArray:datas onItemClicked:nil];
 [sharePicker autorelease];
 }
}

QfShareItem::QfShareItem(QQuickPaintedItem '''parent) :
 QQuickPaintedItem(parent)
{
 m_shareString.clear();
 m_shareUrl.clear();

 connect(this, &amp;QQuickPaintedItem::parentChanged, [this](QQuickItem''' newParent){

 if(newParent)
 {
 newParent->setFiltersChildMouseEvents(true);
 }
 });
 this->installEventFilter(this);

setFlag(QQuickPaintedItem::ItemHasContents, true);
 setFlag(QQuickPaintedItem::ItemClipsChildrenToShape, true);
 setFlag(QQuickPaintedItem::ItemAcceptsDrops, true);
 setRenderTarget(QQuickPaintedItem::InvertedYFramebufferObject);
}

void QfShareItem::paint(QPainter *painter)
{
 try
 {
 Q_UNUSED(painter);
 }
 catch(std::exception&amp;amp; exception)
 {
 qDebug()<<"exception: "<<exception.what();
 }
}

void QfShareItem::shareContent(QString text, QUrl url)
{
 if(!text.isEmpty())
 {
 m_shareString = text;
 }

if(!url.isEmpty())
 {
 m_shareUrl = url;
 }

shareCurrentContent();
}
  1. Register new type to use in QML.
qmlRegisterType<YourShareItem>(uri, 1, 1, "YourShareItem");

How to use in QML.

Import the new type to your QML file where you need to use share logic and add this code:

Button {
 id: btnLink
 width: 22
 height: 22

onClicked: {
 share.shareContent();
 }

QfShareItem {
 id: share
 anchors.fill: btnLink
 shareUrl: userPanelView.shareUrl
 }
}

Summary