If your action has no helper associated with it (so you just want to check if the user is authorized before going on), the next step is just doing the following:

If your action has no helper associated with it (so you just want to check if the user is authorized before going on), the next step is just doing the following:

−

<code cpp>

+

<syntaxhighlight lang="cpp">

KAuth::ActionReply reply = readAction.execute();

KAuth::ActionReply reply = readAction.execute();

if (reply.failed()) {

if (reply.failed()) {

Line 40:

Line 40:

The basics are pretty much the same. This is how the snippet changes:

The basics are pretty much the same. This is how the snippet changes:

−

<code cpp>

+

<syntaxhighlight lang="cpp">

KAuth::Action readAction = "org.kde.auth.example.read";

KAuth::Action readAction = "org.kde.auth.example.read";

readAction.setHelperID("org.kde.auth.example");

readAction.setHelperID("org.kde.auth.example");

Line 64:

Line 64:

In the previous examples all the actions have been executed synchronously. However, when you have an action attached to an helper which is likely to be taking a long time, a synchronous approach is not very well fitting. KAuth is able to handle action execution asynchronously just by setting ''Action::setExecutesAsync(true)''. To monitor the action's progress there's a new object, ''ActionWatcher'', that can be used for this purpose. Let's see how a long action could be handled:

In the previous examples all the actions have been executed synchronously. However, when you have an action attached to an helper which is likely to be taking a long time, a synchronous approach is not very well fitting. KAuth is able to handle action execution asynchronously just by setting ''Action::setExecutesAsync(true)''. To monitor the action's progress there's a new object, ''ActionWatcher'', that can be used for this purpose. Let's see how a long action could be handled:

−

<code cpp>

+

<syntaxhighlight lang="cpp">

void MainWindow::on_longAction_triggered()

void MainWindow::on_longAction_triggered()

{

{

Line 113:

Line 113:

You can easily check the error type through ''ActionReply::type'':

You can easily check the error type through ''ActionReply::type'':

−

<code cpp>

+

<syntaxhighlight lang="cpp">

if (reply.failed())

if (reply.failed())

{

{

Line 142:

Line 142:

Let's see how the longAction example changes when dealing with a KPushButton:

Let's see how the longAction example changes when dealing with a KPushButton:

Using actions in your applications

Now that you've learned the basic KAuth concepts and how to register a set of actions into the system, it's time to see how to actually use KAuth actions inside your application. This tutorial will cover the caller side: how to implement an helper associated to an action will be covered in the next tutorial.

A simple case: creating and executing an action that has no helper associated

Creating an action in your code is rather simple:

Action readAction = "org.kde.auth.example.read";

As you can see, Actions are usually created on the stack and just when needed. To create an action, you just have to specify its own identifier.

If your action has no helper associated with it (so you just want to check if the user is authorized before going on), the next step is just doing the following:

KAuth::ActionReplyreply=readAction.execute();if(reply.failed()){QMessageBox::information(this,"Error",QString("KAuth returned an error code: %1").arg(reply.errorCode()));}else{// Do your stuff here...}</code>''Action::execute()''startsupallthephasesfromauthorizationtoexecutionandreturnsanActionReply.Inourcase,ifthereplyfailedisbecausetheauthorizationwasunsuccessful:inanycase,ActionReplycarriesadditionalinformationabouttheerroroccurred.===Creatingandexecutinganactionthathasanhelperattachedtoit===Thebasicsareprettymuchthesame.Thisishowthesnippetchanges:<syntaxhighlightlang="cpp">KAuth::ActionreadAction="org.kde.auth.example.read";readAction.setHelperID("org.kde.auth.example");QVariantMapargs;args["filename"]=filename;readAction.setArguments(args);KAuth::ActionReplyreply=readAction.execute();if(reply.failed()){QMessageBox::information(this,"Error",QString("KAuth returned an error code: %1").arg(reply.errorCode()));}else{contents=reply.data()["contents"].toString();}</code>Therearemoreparametersthistime.Firstofall,thehelperhastobeexplicitelydeclaredthroughout''Action::setHelperID''.Thisisalsodonetopreventcallinganhelperaccidentally.Wearealsoabletopasssomeparameterstothehelper,through''Action::setArguments''.Intheverysameway,thehelper,uponsuccess,isabletogivebacktotheapplicationaQVariantMap,accessiblethrough''ActionReply::data()''.Inthiscase,''Action::execute()''alsolaunchestheexecutionphaseofthehelper,giventhattheauthorizationwassuccessful.Therearemoreadvancedusagesforhelperactions,suchasprogressreportinganddataretrievalduringexecution,butthesewillbecoveredinthenexttutorial.===Executingactionsasynchronously===Inthepreviousexamplesalltheactionshavebeenexecutedsynchronously.However,whenyouhaveanactionattachedtoanhelperwhichislikelytobetakingalongtime,asynchronousapproachisnotverywellfitting.KAuthisabletohandleactionexecutionasynchronouslyjustbysetting''Action::setExecutesAsync(true)''.Tomonitortheaction'sprogressthere'sanewobject,''ActionWatcher'',thatcanbeusedforthispurpose.Let'sseehowalongactioncouldbehandled:<syntaxhighlightlang="cpp">voidMainWindow::on_longAction_triggered(){ActionlongAction="org.kde.auth.example.longaction";connect(longAction.watcher(),SIGNAL(progressStep(int)),progressBar,SLOT(setValue(int)));connect(longAction.watcher(),SIGNAL(actionPerformed(ActionReply)),this,SLOT(longActionPerformed(ActionReply)));longAction.setExecutesAsync(true);ActionReplyearlyReply=longAction.execute();if(earlyReply.failed()){this->statusBar()->showMessage("Could not execute the long action");}//...}voidMainWindow::stopLongAction(){Action("org.kde.auth.example.longaction").stop();}voidMainWindow::longActionPerformed(ActionReplyreply){//...if(reply.succeeded())this->statusBar()->showMessage("Action succeeded",10000);elsethis->statusBar()->showMessage(QString("Could not execute the long action: %1").arg(reply.errorCode()),10000);}</code>Asyoucansee,we'reusingthewatchertomonitortheprogressandtheresult.Pleasenotethateveniftheactionisasynchronousacheckonanearlyreplyisperformed:thisisbecausewithsomeauthorizationsystemstheauthorizationmighttakeplaceveryearly,andhencebeforetheasyncronousactionreturnstotheeventloop.Also,notethatasyncronousactionsmaybestoppedwith''Action::stop()''==HandlingActionReply==Asyouhaveseeninthepreviousexamples,actionexecutionalwaysreturnsan''ActionReply''.Let'sseehowtohandleit===Handlingerrors===''ActionReply''hastwomainpossiblestatuses:''Success''or''Failed''.Incaseoffailure,theerrorcouldbeassociatedtotwodifferentsources:*KAuth'sinternals*Anerrorintheexecutionphase(e.g.:thehelperencounteredanerror)Youcaneasilychecktheerrortypethrough''ActionReply::type'':<syntaxhighlightlang="cpp">if(reply.failed()){if(reply.type()==ActionReply::KAuthError){// There has been an internal KAuth errorKMessageBox::error(this,i18n("Unable to authenticate/execute the action: %1, %2",reply.errorCode(),reply.errorDescription()));}else{// Our helper triggered a custom error// Act accordingly...}}</code>''ActionReply::KAuthError''isareservedtypethatreportsaninternalerrorhappenedinKAuth.Thiscouldalsomeanafailureintheauthorization/authenticationphase:youhavetochecktheerrorcodeforthat.Otherwise,itmeansthehelperthrewanerror(asyouwillseeinthenexttutorial):inthiscase,errorCodeanddescriptionareprovidedbythehelperitself===Gettingbackdata===Justlike''Action''has'''arguments''',''ActionReply''has'''data''',whichworksinaverysimilarflavour.Uponasuccessfulreply,youcanuse''ActionReply::data()''toobtainaQVariantMapcarryingsomecustomdatastreamedfromthehelper===Differenceswhenusingornotusinganhelper===Whennotusinganhelper,ActionReplywilljustreportsuccesswithoutanydataattachedtoitoran''ActionReply::KAuthError''.==IntegratingKAuthActionsintoKDEUIelements==KDEprovidesawaytointegrateKAuthactionseamlesslyintoauserinterface.UIelementssuchas''KPushButton''canbeassociatedwithanaction,andwillupdatetheirappearancebasedontheaction'sstatus.Also,KPushButtonisabletoperformanearlyauthorization,ifsupportedbytheauthorizationsystem,beforenotifyingbacktheapplication.===IntegratingKPushButton===Let'sseehowthelongActionexamplechangeswhendealingwithaKPushButton:<syntaxhighlightlang="cpp">voidMainWindow::setupAction(){KPushButton*button=newKPushButton;Action*longAction=newAction("org.kde.auth.example.longaction");connect(longAction->watcher(),SIGNAL(progressStep(int)),progressBar,SLOT(setValue(int)));connect(longAction->watcher(),SIGNAL(actionPerformed(ActionReply)),this,SLOT(longActionPerformed(ActionReply)));longAction.setExecutesAsync(true);button->setAuthAction(longAction);connect(button,SIGNAL(authorized(KAuth::Action*)),this,SLOT(performAction(KAuth::Action*)));}voidMainWindow::performAction(KAuth::Action*action){ActionReplyearlyReply=action->execute();if(earlyReply.failed()){this->statusBar()->showMessage("Could not execute the long action");}//...}voidMainWindow::stopLongAction(){Action("org.kde.auth.example.longaction").stop();}voidMainWindow::longActionPerformed(ActionReplyreply){//...if(reply.succeded())this->statusBar()->showMessage("Action succeded",10000);elsethis->statusBar()->showMessage(QString("Could not execute the long action: %1").arg(reply.errorCode()),10000);}</code>Asyoumaynotice,heretheactionisallocatedontheheapthrough''new''.ThisisbecauseKPushButtonwillkeepareferencetothesameactionthroughoutallhisvitalcycle,inadifferentflavourcomparedtowhatwe'veseenbefore.Let'sseewhathappens.Hereweassociate''longAction''to''button''.Pleasenotethatweconnectto''authorized''andnot''clicked''.''authorized''getsemittedonlyifthebuttonwasclickedandtheactionpassedtheearlyauthorizationphase.Donethat,inourslotwecandecidetostartupexplicitelytheexecutionordosomethingelsebeforethat.Tothebottomline,associatingactionstoKPushButtonsisagreatideaifyouwanttostartupanactiondynamically,andgettinggoodandconsistentvisualintegrationwhiledoingit.===OtherGUIelements===Asoftoday,KAuthisalsoabletointegratewith''KAction''withanalmostidenticalworkflow,thathencewon'tbecoveredhere,astheAPIisidentical.==Conclusion==Asyouhaveseen,therearelotsofwaystouseanactioninyourapplication,andmostofthetimesthebestsolutiondependsonwhatyou'retryingtoachieve.AgoodreadingandadvisedreadingistheKAuth::ActionAPIdocumentation,whichisquiteextensiveandcoverseverythingthatwasshowninthistutorial