table of contentsread.pudn.com/downloads767/ebook/3045877/qt 5 blueprints.pdftable of contents qt 5...

262

Upload: others

Post on 11-Jul-2020

8 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount
Page 2: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

TableofContentsQt5BlueprintsCreditsAbouttheAuthorAbouttheReviewerswww.PacktPub.comSupportfiles,eBooks,discountoffers,andmore

Whysubscribe?FreeaccessforPacktaccountholders

PrefaceWhatthisbookcoversWhatyouneedforthisbookWhothisbookisforConventionsReaderfeedbackCustomersupport

DownloadingtheexamplecodeErrataPiracyQuestions

1.CreatingYourFirstQtApplicationCreatinganewprojectChangingthelayoutofwidgetsUnderstandingthemechanismofsignalsandslotsConnectingtwosignalsCreatingaQtQuickapplicationConnectingC++slotstoQMLsignalsSummary

2.BuildingaBeautifulCross-platformClockCreatingabasicdigitalclockTweakingthedigitalclockSavingandrestoringsettingsBuildingontheUnixplatformsSummary

3.CookinganRSSReaderwithQtQuickUnderstandingmodelandviewParsingRSSFeedsbyXmlListModelTweakingthecategoriesUtilizingScrollViewAddingBusyIndicator

Page 3: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

MakingaframelesswindowDebuggingQMLSummary

4.ControllingCameraandTakingPhotosAccessingthecamerainQtControllingthecameraDisplayingerrorsonthestatusbarPermanentwidgetsinthestatusbarUtilizingthemenubarUsingQFileDialogQMLcameraSummary

5.ExtendingPaintApplicationswithPluginsDrawingviaQPainterWritingstaticpluginsWritingdynamicpluginsMergingpluginsandmainprogramprojectsCreatingaC++pluginforQMLapplicationsSummary

6.GettingWiredandManagingDownloadsIntroducingQtnetworkprogrammingUtilizingQNetworkAccessManagerMakinguseoftheprogressbarWritingmultithreadedapplicationsManagingasystemnetworksessionSummary

7.ParsingJSONandXMLDocumentstoUseOnlineAPIsSettingupQtforAndroidParsingJSONresultsParsingXMLresultsBuildingQtapplicationsforAndroidParsingJSONinQMLSummary

8.EnablingYourQtApplicationtoSupportOtherLanguagesInternationalizationofQtapplicationsTranslatingQtWidgetsapplicationsDisambiguatingidenticaltextsChanginglanguagesdynamicallyTranslatingQtQuickapplicationsSummary

9.DeployingApplicationsonOtherDevicesReleasingQtapplicationsonWindowsCreatinganinstaller

Page 4: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

PackagingQtapplicationsonLinuxDeployingQtapplicationsonAndroidSummary

10.Don'tPanicWhenYouEncounterTheseIssuesCommonlyencounteredissues

C++syntaxmistakesPointerandmemoryIncompatiblesharedlibrariesDoesn'trunonAndroid!

DebuggingQtapplicationsDebuggingQtQuickapplicationsUsefulresourcesSummary

Index

Page 5: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

Chapter1.CreatingYourFirstQtApplicationGUIprogrammingisnotasdifficultasyouthink.Atleastit'snotwhenyoucometotheworldofQt.Thisbookwilltakeyouthroughthisworldandgiveyouaninsightintothisincrediblyamazingtoolkit.Itdoesn'tmatterwhetheryou'veheardofitornot,aslongasyouhaveessentialknowledgeofC++programming.

Inthischapter,wewillgetyoucomfortablewiththedevelopmentofQtapplications.Simpleapplicationsareusedasademonstrationforyoutocoverthefollowingtopics:

CreatinganewprojectChangingthelayoutofwidgetsUnderstandingthemechanismofsignalsandslotsConnectingtwosignalsCreatingaQtQuickapplicationConnectingC++slotstoQMLsignals

CreatinganewprojectIfyouhaven'tinstalledQt5,refertohttp://www.qt.io/downloadtoinstallthelatestversionofit.It'srecommendedthatyouinstalltheCommunityversion,whichistotallyfreeandcompliantwithGPL/LGPL.Typically,theinstallerwillinstallbothQtLibraryandQtCreatorforyou.Inthisbook,wewilluseQt5.4.0andQtCreator3.3.0.Laterversionsmayhaveslightdifferencesbuttheconceptremainsthesame.It'shighlyrecommendedthatyouinstallQtCreatorifyoudon'thaveitonyourcomputer,becauseallthetutorialsinthisbookarebasedonit.ItisalsotheofficialIDEforthedevelopmentofQtapplications.AlthoughyoumaybeabletodevelopQtapplicationswithotherIDEs,ittendstobemuchmorecomplex.Soifyou'reready,let'sgoforitbyperformingthefollowingsteps:

1. OpenQtCreator.2. NavigatetoFile|NewFileorProject.3. SelectQtWidgetsApplication.4. Entertheproject'snameandlocation.Inthiscase,theproject'snameis

layout_demo.

Youmaywishtofollowthewizardandkeepthedefaultvalues.Afterthisprocess,QtCreatorwillgeneratetheskeletonoftheprojectbasedonyourchoices.TheUIfilesareundertheFormsdirectory.Whenyoudouble-clickonaUIfile,QtCreatorwill

Page 6: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

redirectyoutotheintegrateddesigner.ThemodeselectorshouldhaveDesignhighlighted,andthemainwindowshouldcontainseveralsub-windowstoletyoudesigntheuserinterface.Thisisexactlywhatwearegoingtodo.FormoredetailsaboutQtCreatorUI,refertohttp://doc.qt.io/qtcreator/creator-quick-tour.html.

Dragthreepushbuttonsfromthewidgetbox(widgetpalette)intotheframeofMainWindowinthecenter.ThedefaulttextdisplayedonthesebuttonsisPushButton,butyoucanchangethetextifyouwantbydouble-clickingonthebutton.Inthiscase,IchangedthebuttonstoHello,Hola,andBonjour,accordingly.Notethatthisoperationwon'taffecttheobjectNameproperty.Inordertokeepitneatandeasytofind,weneedtochangetheobjectNameproperty.Theright-handsideoftheUIcontainstwowindows.Theupper-rightsectionincludesObjectInspectorandthelower-rightsideincludesPropertyEditor.Justselectapushbutton;youcaneasilychangeobjectNameinPropertyEditor.Forthesakeofconvenience,Ichangedthesebuttons'objectNamepropertiestohelloButton,holaButton,andbonjourButtonrespectively.

TipIt'sagoodhabittouselowercaseforthefirstletterofobjectNameandanuppercaseletterforClassname.Thishelpsyourcodetobemorereadablebypeoplewhoarefamiliarwiththisconvention.

Okay,it'stimetoseewhatyouhavedonetotheuserinterfaceofyourfirstQtapplication.ClickonRunontheleft-handsidepanel.Itwillbuildtheprojectautomaticallyandthenrunit.It'samazingtoseethattheapplicationhastheexactsameinterfaceasthedesign,isn'tit?Ifeverythingisalright,theapplicationshouldappearsimilartowhatisshowninthefollowingscreenshot:

Page 7: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

Youmaywanttolookatthesourcecodeandseewhathappenedthere.So,let'sgobacktothesourcecodebyreturningtotheEditmode.ClickontheEditbuttoninthemodeselector.Then,double-clickonmain.cppintheSourcesfolderoftheProjectstreeview.Thecodeformain.cppisshownasfollows:

#include"mainwindow.h"

#include<QApplication>

intmain(intargc,char*argv[])

{

QApplicationa(argc,argv);

MainWindoww;

w.show();

returna.exec();

}

NoteTheQApplicationclassmanagestheGUIapplication'scontrolflowandthemainsettings.

Actually,youdon'tneedtoandyouprobablywon'tchangetoomuchinthisfile.Thefirstlineofthemainscopejustinitializestheapplicationsonauser'sdesktopandhandlessomeevents.Thenthereisalsoanobject,w,whichbelongstotheMainWindowclass.Asforthelastline,itensuresthattheapplicationwon'tterminateafterexecutionbutwillkeepinaneventloop,sothatitisabletorespondtoexternaleventssuchasmouseclicksandwindowstatechanges.

Lastbutnotleast,let'sseewhathappensduringtheinitializationoftheMainWindow

Page 8: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

object,w.Itisthecontentofmainwindow.h,shownasfollows:

#ifndefMAINWINDOW_H

#defineMAINWINDOW_H

#include<QMainWindow>

namespaceUi{

classMainWindow;

}

classMainWindow:publicQMainWindow

{

Q_OBJECT

public:

explicitMainWindow(QWidget*parent=0);

~MainWindow();

private:

Ui::MainWindow*ui;

};

#endif//MAINWINDOW_H

YoumayfeelabitsurprisedseeingaQ_OBJECTmacroifthisisyourfirsttimewritingaQtapplication.IntheQObjectdocumentation,itsays:

TheQ_OBJECTmacromustappearintheprivatesectionofaclassdefinitionthatdeclaresitsownsignalsandslotsorthatusesotherservicesprovidedbyQt'smeta-

objectsystem.

Well,thismeansthatQObjecthastobedeclaredifyou'regoingtouseQt'smeta-objectsystemand(or)itssignalsandslotsmechanism.Thesignalsandslots,whicharealmostthecoreofQt,willbeincludedlaterinthischapter.

Thereisaprivatemembernamedui,whichisapointeroftheMainWindowclassoftheUinamespace.DoyouremembertheUIfileweeditedbefore?WhatthemagicofQtdoesisthatitlinkstheUIfileandtheparentalsourcecode.WecanmanipulatetheUIthroughcodelinesaswellasdesignitinQtCreator'sintegrateddesigner.Finally,let'slookintotheconstructionfunctionofMainWindowinmainwindow.cpp:

#include"mainwindow.h"

#include"ui_mainwindow.h"

MainWindow::MainWindow(QWidget*parent):

QMainWindow(parent),

Page 9: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

ui(newUi::MainWindow)

{

ui->setupUi(this);

}

MainWindow::~MainWindow()

{

deleteui;

}

Didyouseewheretheuserinterfacecomesfrom?It'sthemembersetupUifunctionofUi::MainWindowthatinitializesitandsetsitupforus.Youmaywanttocheckwhathappensifwechangethememberfunctiontosomethinglikethis:

MainWindow::MainWindow(QWidget*parent):

QMainWindow(parent),

ui(newUi::MainWindow)

{

ui->setupUi(this);

ui->holaButton->setEnabled(false);

}

Whathappenedhere?TheHolabuttoncan'tbeclickedonbecausewedisabledit!Ithasthesameeffectiftheenabledboxisuncheckedinthedesignerinsteadofwritingastatementhere.Pleaseapplythischangebeforeheadingtothenexttopic,becausewedon'tneedadisabledpushbuttontodoanydemonstrationsinthischapter.

Page 10: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

ChangingthelayoutofwidgetsYoualreadyknowhowtoaddandmovewidgetsintheDesignmode.Now,weneedtomaketheUIneatandtidy.I'llshowyouhowtodothisstepbystep.

AquickwaytodeleteawidgetistoselectitandpresstheDeletebutton.Meanwhile,somewidgets,suchasthemenubar,statusbar,andtoolbarcan'tbeselected,sowehavetoright-clickontheminObjectInspectoranddeletethem.Sincetheyareuselessinthisexample,it'ssafetoremovethemandwecandothisforgood.

Okay,let'sunderstandwhatneedstobedoneaftertheremoval.Youmaywanttokeepallthesepushbuttonsonthesamehorizontalaxis.Todothis,performthefollowingsteps:

1. SelectallthepushbuttonseitherbyclickingonthemonebyonewhilekeepingtheCtrlkeypressedorjustdrawinganenclosingrectanglecontainingallthebuttons.

2. Right-clickandselectLayout|LayOutHorizontally,ThekeyboardshortcutforthisisCtrl+H.

3. ResizethehorizontallayoutandadjustitslayoutSpacingbyselectingitanddragginganyofthepointsaroundtheselectionboxuntilitfitsbest.

Hmm…!YoumayhavenoticedthatthetextoftheBonjourbuttonislongerthantheothertwobuttons,anditshouldbewiderthantheothers.Howdoyoudothis?Youcanchangethepropertyofthehorizontallayoutobject'slayoutStretchpropertyinPropertyEditor.Thisvalueindicatesthestretchfactorsofthewidgetsinsidethehorizontallayout.Theywouldbelaidoutinproportion.Changeitto3,3,4,andthereyouare.Thestretchedsizedefinitelywon'tbesmallerthantheminimumsizehint.Thisishowthezerofactorworkswhenthereisanonzeronaturalnumber,whichmeansthatyouneedtokeeptheminimumsizeinsteadofgettinganerrorwithazerodivisor.

Now,dragPlainTextEditjustbelow,andnotinside,thehorizontallayout.Obviously,itwouldbeneaterifwecouldextendtheplaintextedit'swidth.However,wedon'thavetodothismanually.Infact,wecouldchangethelayoutoftheparent,MainWindow.That'sit!Right-clickonMainWindow,andthennavigatetoLayout|LayOutVertically.Wow!AllthechildrenwidgetsareautomaticallyextendedtotheinnerboundaryofMainWindow;theyarekeptinaverticalorder.You'llalsofindLayoutsettingsinthecentralWidgetproperty,whichisexactlythesamethingastheprevioushorizontallayout.

Thelastthingtomakethisapplicationhalfwaydecentistochangethetitleofthewindow.MainWindowisnotthetitleyouwant,right?ClickonMainWindowinthe

Page 11: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

objecttree.Then,scrolldownitspropertiestofindwindowTitle.Nameitwhateveryouwant.Inthisexample,IchangedittoGreeting.Now,runtheapplicationagainandyouwillseeitlookslikewhatisshowninthefollowingscreenshot:

Page 12: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

UnderstandingthemechanismofsignalsandslotsItisreallyimportanttokeepyourcuriosityandtoexplorewhatonearththesepropertiesdo.However,pleaseremembertorevertthechangesyoumadetotheapp,asweareabouttoenterthecorepartofQt,thatis,signalsandslots.

NoteSignalsandslotsareusedforcommunicationbetweenobjects.ThesignalsandslotsmechanismisacentralfeatureofQtandprobablythepartthatdiffersthemostfromthefeaturesprovidedbyotherframeworks.

HaveyoueverwonderedwhyawindowclosesaftertheClosebuttonisclickedon?DeveloperswhoarefamiliarwithothertoolkitswouldsaythattheClosebuttonbeingclickedonisanevent,andthiseventisboundwithacallbackfunctionthatisresponsibleforclosingthewindow.Well,it'snotquitethesameintheworldofQt.SinceQtusesamechanismcalledsignalsandslots,itmakesthecallbackfunctionweaklycoupledtotheevent.Also,weusuallyusethetermssignalandslotinQt.Asignalisemittedwhenaparticulareventoccurs.Aslotisafunctionthatiscalledinresponsetoaparticularsignal.Thefollowingsimpleandschematicdiagramhelpsyouunderstandtherelationbetweensignals,events,andslots:

Qthastonsofpredefinedsignalsandslots,whichcoveritsgeneralpurposes.However,it'sindeedcommonplacetoaddyourownslotstohandlethetargetsignals.Youmayalsobeinterestedinsubclassingwidgetsandwritingyourownsignals,whichwillbecoveredlater.Themechanismofsignalsandslotswasdesignedtobetype-safebecauseofitsrequirementofthelistofthesamearguments.Infact,theslotmayhaveashorterargumentslistthanthesignalsinceitcanignoretheextras.Youcanhaveasmanyargumentsasyouwant.Thisenablesyoutoforgetaboutthe

Page 13: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

wildcardvoid*typeinCandothertoolkits.

SinceQt5,thismechanismisevensaferbecausewecanuseanewsyntaxofsignalsandslotstodealwiththeconnections.Aconversionofapieceofcodeisdemonstratedhere.Let'sseewhatatypicalconnectstatementinoldstyleis:

connect(sender,SIGNAL(textChanged(QString)),receiver,

SLOT(updateText(QString)));

Thiscanberewritteninanewsyntaxstyle:

connect(sender,&Sender::textChanged,receiver,

&Receiver::updateText);

Inthetraditionalwayofwritingcode,theverificationofsignalsandslotsonlyhappensatruntime.Inthenewstyle,thecompilercandetectthemismatchesinthetypesofargumentsandtheexistenceofsignalsandslotsatcompiletime.

NoteAslongasitispossible,allconnectstatementsarewritteninthenewsyntaxstyleinthisbook.

Now,let'sgetbacktoourapplication.I'llshowyouhowtodisplaysomewordsinaplaintexteditwhentheHellobuttonisclickedon.Firstofall,weneedtocreateaslotsinceQthasalreadypredefinedtheclickedsignalfortheQPushButtonclass.Editmainwindow.handaddaslotdeclaration:

#ifndefMAINWINDOW_H

#defineMAINWINDOW_H

#include<QMainWindow>

namespaceUi{

classMainWindow;

}

classMainWindow:publicQMainWindow

{

Q_OBJECT

public:

explicitMainWindow(QWidget*parent=0);

~MainWindow();

Page 14: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

privateslots:

voiddisplayHello();

private:

Ui::MainWindow*ui;

};

#endif//MAINWINDOW_H

Asyoucansee,it'stheslotskeywordthatdistinguishesslotsfromordinaryfunctions.Ideclareditprivatetorestrictaccesspermission.Youhavetodeclareitapublicslotifyouneedtoinvokeitinanobjectfromotherclasses.Afterthisdeclaration,wehavetoimplementitinthemainwindow.cppfile.TheimplementationofthedisplayHelloslotiswrittenasfollows:

voidMainWindow::displayHello()

{

ui->plainTextEdit->appendPlainText(QString("Hello"));

}

ItsimplycallsamemberfunctionoftheplaintexteditinordertoaddaHelloQStringtoit.QStringisacoreclassthatQthasintroduced.ItprovidesaUnicodecharacterstring,whichefficientlysolvestheinternationalizationissue.It'salsoconvenienttoconvertaQStringclasstostd::stringandviceversa.Besides,justliketheotherQObjectclasses,QStringusesanimplicitsharingmechanismtoreducememoryusageandavoidneedlesscopying.Ifyoudon'twanttogetconcernedaboutthescenesshowninthefollowingcode,justtakeQStringasanimprovedversionofstd::string.Now,weneedtoconnectthisslottothesignalthattheHellopushbuttonwillemit:

MainWindow::MainWindow(QWidget*parent):

QMainWindow(parent),

ui(newUi::MainWindow)

{

ui->setupUi(this);

connect(ui->helloButton,&QPushButton::clicked,this,

&MainWindow::displayHello);

}

WhatIdidisaddaconnectstatementtotheconstructorofMainWindow.Infact,wecanconnectsignalsandslotsanywhereandatanytime.However,theconnectiononlyexistsafterthislinegetsexecuted.So,it'sacommonpracticetohavelotsofconnectstatementsintheconstructionfunctionsinsteadofspreadingthemout.Forabetterunderstanding,runyourapplicationandseewhathappenswhenyouclickontheHellobutton.Everytimeyouclick,aHellotextwillbeappendedtotheplaintext

Page 15: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

edit.ThefollowingscreenshotiswhathappenedafterweclickedontheHellobuttonthreetimes:

Gettingconfused?Letmewalkyouthroughthis.WhenyouclickedontheHellobutton,itemittedaclickedsignal.Then,thecodeinsidethedisplayHelloslotgotexecuted,becauseweconnectedtheclickedsignaloftheHellobuttontothedisplayHelloslotofMainWindow.WhatthedisplayHelloslotdidisthatitsimplyappendedHellototheplaintextedit.

Itmaytakeyousometimetofullyunderstandthemechanismofsignalsandslots.Justtakeyourtime.I'llshowyouanotherexampleofhowtodisconnectsuchaconnectionafterweclickedontheHolabutton.Similarly,addadeclarationoftheslottotheheaderfileanddefineitinthesourcefile.Ipastedthecontentofthemainwindow.hheaderfile,asfollows:

#ifndefMAINWINDOW_H

#defineMAINWINDOW_H

#include<QMainWindow>

namespaceUi{

classMainWindow;

}

classMainWindow:publicQMainWindow

{

Q_OBJECT

public:

explicitMainWindow(QWidget*parent=0);

~MainWindow();

Page 16: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

privateslots:

voiddisplayHello();

voidonHolaClicked();

private:

Ui::MainWindow*ui;

};

#endif//MAINWINDOW_H

It'sonlydeclaringaonHolaClickedslotthatdifferedfromtheoriginal.Here'sthecontentofthesourcefile:

#include"mainwindow.h"

#include"ui_mainwindow.h"

MainWindow::MainWindow(QWidget*parent):

QMainWindow(parent),

ui(newUi::MainWindow)

{

ui->setupUi(this);

connect(ui->helloButton,&QPushButton::clicked,this,

&MainWindow::displayHello);

connect(ui->holaButton,&QPushButton::clicked,this,

&MainWindow::onHolaClicked);

}

MainWindow::~MainWindow()

{

deleteui;

}

voidMainWindow::displayHello()

{

ui->plainTextEdit->appendPlainText(QString("Hello"));

}

voidMainWindow::onHolaClicked()

{

ui->plainTextEdit->appendPlainText(QString("Hola"));

disconnect(ui->helloButton,&QPushButton::clicked,this,

&MainWindow::displayHello);

}

You'llfindthattheHellobuttonnolongerworksafteryouclickedontheHolabutton.ThisisbecauseintheonHolaClickedslot,wejustdisconnectedthebindingbetweentheclickedsignalofhelloButtonandthedisplayHelloslotofMainWindow.Actually,disconnecthassomeoverloadedfunctionsandcanbeusedinamoredestructiveway.Forexample,youmaywanttodisconnectallconnectionsbetweenaspecific

Page 17: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

signalsenderandaspecificreceiver:

disconnect(ui->helloButton,0,this,0);

Ifyouwanttodisconnectalltheslotsassociatedwithasignal,sinceasignalcanbeconnectedtoasmanyslotsasyouwish,thecodecanbewrittenlikethis:

disconnect(ui->helloButton,&QPushButton::clicked,0,0);

Wecanalsodisconnectallthesignalsinanobject,whateverslotstheymightbeconnectedto.ThefollowingcodewilldisconnectallthesignalsinhelloButton,whichofcourseincludestheclickedsignal:

disconnect(ui->helloButton,0,0,0);

Justlikeasignal,aslotcanbeconnectedtoasmanysignalsasyouwant.However,there'snosuchfunctiontodisconnectaspecificslotfromallthesignals.

TipAlwaysrememberthesignalsandslotsthatyouhaveconnected.

Apartfromthenewsyntaxfortraditionalconnectionsofsignalsandslots,Qt5hasofferedanewwaytosimplifysuchabindingprocesswithC++11lambdaexpressions.Asyoumayhavenoticed,it'skindoftedioustodeclareaslotintheheaderfile,defineitinthesourcecodefile,andthenconnectittoasignal.It'sworthwhileiftheslothasalotofstatements,otherwiseitbecomestimeconsumingandincreasesthecomplexity.Beforewegoanyfurther,weneedtoturnonC++11supportonQt.Edittheprofile(layout_demo.proinmyexample)andaddthefollowinglinetoit:

CONFIG+=c++11

NoteNotethatsomeoldcompilersdon'tsupportC++11.Ifthishappens,upgradeyourcompiler.

Now,youneedtonavigatetoBuild|Runqmaketoreconfiguretheprojectproperly.

Page 18: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

Ifeverythingisokay,wecangobacktoeditingthemainwindow.cppfile.Thisway,thereisnoneedtodeclareaslotanddefineandconnectit.JustaddaconnectstatementtotheconstructionfunctionofMainWindow:

connect(ui->bonjourButton,&QPushButton::clicked,[this](){

ui->plainTextEdit->appendPlainText(QString("Bonjour"));

});

It'sverystraightforward,isn'tit?Thethirdargumentisalambdaexpression,whichwasaddedtoC++sinceC++11.

NoteFormoredetailsaboutlambdaexpression,visithttp://en.cppreference.com/w/cpp/language/lambda.

Thispairofsignalandslotconnectionisdoneifyoudon'tdoneedtotodisconnectsuchaconnection.However,ifyouneed,youhavetosavethisconnection,whichisaQMetaObject::Connectiontype.Inordertodisconnectthisconnectionelsewhere,itwouldbebettertodeclareitasavariableofMainWindow.Sotheheaderfilebecomesasfollows:

#ifndefMAINWINDOW_H

#defineMAINWINDOW_H

#include<QMainWindow>

namespaceUi{

classMainWindow;

}

classMainWindow:publicQMainWindow

{

Q_OBJECT

public:

explicitMainWindow(QWidget*parent=0);

~MainWindow();

privateslots:

voiddisplayHello();

voidonHolaClicked();

private:

Ui::MainWindow*ui;

QMetaObject::ConnectionbonjourConnection;

};

Page 19: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

#endif//MAINWINDOW_H

Here,IdeclaredbonjourConnectionasanobjectofQMetaObject::Connectionsothatwecansavetheconnectiondealingwithanunnamedslot.Similarly,thedisconnectionhappensinonHolaClicked,sotherewon'tbeanynewBonjourtextonscreenafterweclickontheHolabutton.Hereisthecontentofmainwindow.cpp:

#include"mainwindow.h"

#include"ui_mainwindow.h"

MainWindow::MainWindow(QWidget*parent):

QMainWindow(parent),

ui(newUi::MainWindow)

{

ui->setupUi(this);

connect(ui->helloButton,&QPushButton::clicked,this,

&MainWindow::displayHello);

connect(ui->holaButton,&QPushButton::clicked,this,

&MainWindow::onHolaClicked);

bonjourConnection=connect(ui->bonjourButton,

&QPushButton::clicked,[this](){

ui->plainTextEdit-

>appendPlainText(QString("Bonjour"));

});

}

MainWindow::~MainWindow()

{

deleteui;

}

voidMainWindow::displayHello()

{

ui->plainTextEdit->appendPlainText(QString("Hello"));

}

voidMainWindow::onHolaClicked()

{

ui->plainTextEdit->appendPlainText(QString("Hola"));

disconnect(ui->helloButton,&QPushButton::clicked,this,

&MainWindow::displayHello);

disconnect(bonjourConnection);

}

TipDownloadingtheexamplecode

Page 20: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

Youcandownloadtheexamplecodefilesfromyouraccountathttp://www.packtpub.comforallthePacktPublishingbooksyouhavepurchased.Ifyoupurchasedthisbookelsewhere,youcanvisithttp://www.packtpub.com/supportandregistertohavethefilese-maileddirectlytoyou.

Thisisindeedanothernewusageofdisconnect.IttakesinaQMetaObject::Connectionobjectastheonlyargument.You'llthankthisnewoverloadedfunctionifyou'regoingtousethelambdaexpressionasaslot.

Page 21: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

ConnectingtwosignalsDuetotheweakcouplingsoftheQtsignalsandslotmechanisms,itisviabletobindsignalstoeachother.Itmaysoundconfusing,soletmedrawadiagramtomakeitclear:

Whenaneventtriggersaspecificsignal,thisemittedsignalcouldbeanotherevent,whichwillemitanotherspecificsignal.Itisnotaverycommonpractice,butittendstobeusefulwhenyoudealwithsomecomplexsignalsandslotconnectionnetworks,especiallywhentonsofeventsleadtotheemissionofonlyafewsignals.Althoughitdefinitelyincreasesthecomplexityoftheproject,bindingthesesignalscouldsimplifythecodealot.AppendthefollowingstatementtotheconstructionfunctionofMainWindow:

connect(ui->bonjourButton,&QPushButton::clicked,ui-

>helloButton,&QPushButton::clicked);

You'llgettwolinesinaplaintexteditafteryouclickontheBonjourbutton.ThefirstlineisBonjourandthesecondoneisHello.Apparently,thisisbecausewecoupledtheclickedsignaloftheBonjourbuttonwiththeclickedsignaloftheHellobutton.Theclickedsignalofthelatterhasalreadybeencoupledwithaslot,whichresultsinthenewtextline,Hello.Infact,ithasthesameeffectasthefollowingstatement:

connect(ui->bonjourButton,&QPushButton::clicked,[this](){

emitui->helloButton->clicked();

});

Basically,connectingtwosignalsisasimplifiedversionofconnectingasignalandaslot,whiletheslotismeanttoemitanothersignal.Asforpriority,theslot(s)ofthelattersignalwillbehandledwhentheeventloopisreturnedtotheobject.

However,itisimpossibletoconnecttwoslotsbecausethemechanismrequiresasignalwhileaslotisconsideredareceiverinsteadofasender.Therefore,ifyouwanttosimplifytheconnection,justwraptheseslotsasoneslot,whichcanbeusedfor

Page 22: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

connections.

Page 23: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

CreatingaQtQuickapplicationWealreadycoveredhowtocreateaQt(C++)application.HowaboutgivingthenewlyintroducedQtQuickapplicationdevelopmentatry?QtQuickwasintroducedinQt4.8anditisnowbecomingmatureinQt5.BecausetheQMLfileisusuallyplatform-independent,itenablesyoutodevelopanapplicationformultipletargets,includingmobileoperatingsystemswiththesamecode.

Inthischapter,I'llshowyouhowtocreateasimpleQtQuickapplicationbasedonQtQuickControls1.2,asfollows:

1. CreateanewprojectnamedHelloQML.2. SelectQtQuickApplicationinsteadofQtWidgetsApplication,whichwe

chosepreviously.3. SelectQtQuickControls1.2whenthewizardnavigatesyoutoSelectQt

QuickComponentsSet.

QtQuickControlshasbeenintroducedsinceQt5.1andishighlyrecommendedbecauseitenablesyoutobuildacompleteandnativeuserinterface.Youcanalsocontrolthetop-levelwindowpropertiesfromQML.GettingconfusedbyQMLandQtQuick?

NoteQMLisauserinterfacespecificationandprogramminglanguage.Itallowsdevelopersanddesignersaliketocreatehighlyperformant,fluidlyanimated,andvisuallyappealingapplications.QMLoffersahighlyreadable,declarative,JSON-likesyntaxwithsupportforimperativeJavaScriptexpressionscombinedwithdynamicpropertybindings.

WhileQtQuickisthestandardlibraryforQML,itsoundsliketherelationbetweenSTLandC++.ThedifferenceisthatQMLisdedicatedtouserinterfacedesignandQtQuickincludesalotofvisualtypes,animations,andsoon.Beforewegoanyfurther,IwanttoinformyouthatQMLisdifferentfromC++butsimilartoJavaScriptandJSON.

Editthemain.qmlfileundertherootoftheResourcesfile,qml.qrc,whichQtCreatorhasgeneratedforournewQtQuickproject.Let'sseehowthecodeshouldbe:

importQtQuick2.3

importQtQuick.Controls1.2

Page 24: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

ApplicationWindow{

visible:true

width:640

height:480

title:qsTr("HelloQML")

menuBar:MenuBar{

Menu{

title:qsTr("File")

MenuItem{

text:qsTr("Exit")

shortcut:"Ctrl+Q"

onTriggered:Qt.quit()

}

}

}

Text{

id:hw

text:qsTr("HelloWorld")

font.capitalization:Font.AllUppercase

anchors.centerIn:parent

}

Label{

anchors{bottom:hw.top;bottomMargin:5;

horizontalCenter:hw.horizontalCenter}

text:qsTr("HelloQtQuick")

}

}

IfyouhaveevertouchedJavaorPython,thefirsttwolineswon'tbetoounfamiliartoyou.ItsimplyimportsQtQuickandQtQuickControls,andthenumberfollowingistheversionofthelibrary.Youmayneedtochangetheversionifthereisanewerlibrary.ImportingotherlibrariesisacommonpracticewhendevelopingQtQuickapplications.

ThebodyofthisQMLsourcefileisactuallyintheJSONstyle,whichenablesyoutounderstandthehierarchyoftheuserinterfacethroughthecode.Here,therootitemisApplicationWindow,whichisbasicallythesamethingasMainWindowintheprevioustopics,andweusebracestoenclosethestatementsjustlikeinaJSONfile.AlthoughyoucoulduseasemicolontomarkanendingofastatementjustlikewedoinC++,thereisnoneedtodothis.Asyoucansee,thepropertydefinitionneedsacolonifit'sasingle-linestatementandenclosingbracesifitcontainsmorethanonesubproperty.

ThestatementsarekindofselfexplanatoryandtheyaresimilartothepropertiesthatwesawintheQtWidgetsapplication.AqsTrfunctionisusedforinternationalizationandlocalization.StringsmarkedbyqsTrcouldbetranslatedbyQtLinguist.In

Page 25: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

additiontothis,youdon'tneedtocareaboutQStringandstd::stringanymore.AllthestringsinQMLareencodedinthesamecodingastheQMLfileandtheQMLfileiscreatedinUTF-8bydefault.

AsforthesignalsandslotsmechanisminQtQuick,it'seasyifyouonlyuseQMLtowritethecallbackfunctiontothecorrespondingslot.Here,weexecuteQt.quit()insidetheonTriggeredslotofMenuItem.It'sviabletoconnectthesignalofaQMLitemtoaC++object'sslot,whichI'llintroducelater.

WhenyourunthisapplicationinWindows,youcanbarelyfindthedifferencebetweentheTextitemandtheLabelitem.However,onsomeplatforms,orwhenyouchangethesystemfontand/oritscolor,you'llfindthatLabelfollowsthefontandthecolorschemeofthesystem,whileTextdoesn't.AlthoughyoucanusethepropertiesofTexttocustomizetheappearanceofLabel,itwouldbebettertousethesystemsettingstokeepthelooksoftheapplicationnative.Well,ifyourunthisapplicationrightnow,itwillappearsimilartowhatisshowninthefollowingscreenshot:

BecausethereisnoseparateUIfilefortheQtQuickapplications,onlyaQMLfile,weusetheanchorspropertytopositiontheitems,andanchors.centerInwillpositiontheiteminthecenteroftheparent.ThereisanintegratedQtQuickDesignerinQt

Page 26: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

Creator,whichcouldhelpyoudesigntheuserinterfaceofaQtQuickapplication.Ifyouneedit,justnavigatetoDesignmodewhenyou'reeditingaQMLfile.However,IsuggestyoustayinEditmodetounderstandthemeaningofeachstatement.

Page 27: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

ConnectingC++slotstoQMLsignalsTheseparationoftheuserinterfaceandbackendallowsustoconnectC++slotstotheQMLsignals.Althoughit'spossibletowriteprocessingfunctionsinQMLandmanipulateinterfaceitemsinC++,itviolatestheprincipleoftheseparation.Therefore,youmaywanttoknowhowtoconnectaC++slottoaQMLsignalatfirst.AsforconnectingaQMLslottoaC++signal,I'llintroducethatlaterinthisbook.

Inordertodemonstratethis,weneedtocreateaC++classinthefirstplacebyright-clickingontheprojectintheProjectspanelandselectingAddNew….Then,clickonC++Classinthepop-upwindow.ThenewlycreatedclassshouldatleastinheritfromQObjectbychoosingQObjectasitsbaseclass.ThisisbecauseaplainC++classcan'tincludeQt'sslotsorsignals.Theheaderfile'scontentisdisplayedasfollows:

#ifndefPROCESSOR_H

#definePROCESSOR_H

#include<QObject>

classProcessor:publicQObject

{

Q_OBJECT

public:

explicitProcessor(QObject*parent=0);

publicslots:

voidonMenuClicked(constQString&);

};

#endif//PROCESSOR_H

Here'sthecontentofthesourcefile:

#include<QDebug>

#include"processor.h"

Processor::Processor(QObject*parent):

QObject(parent)

{

}

voidProcessor::onMenuClicked(constQString&str)

{

qDebug()<<str;

}

Page 28: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

TheC++fileisthesameastheonewedealtwithintheprevioustopics.TheonMenuClickedslotIdefinedissimplytooutputthestringthatpassesthroughthesignal.NotethatyouhavetoincludeQDebugifyouwanttousethebuilt-infunctionsofqDebug,qWarning,qCritical,andsoon.

Theslotisprepared,soweneedtoaddasignaltotheQMLfile.TheQMLfileischangedtothefollowingcode:

importQtQuick2.3

importQtQuick.Controls1.2

ApplicationWindow{

id:window

visible:true

width:640

height:480

title:qsTr("HelloQML")

signalmenuClicked(stringstr)

menuBar:MenuBar{

Menu{

title:qsTr("File")

MenuItem{

text:qsTr("Exit")

shortcut:"Ctrl+Q"

onTriggered:Qt.quit()

}

MenuItem{

text:qsTr("ClickMe")

onTriggered:window.menuClicked(text)

}

}

}

Text{

id:hw

text:qsTr("HelloWorld")

font.capitalization:Font.AllUppercase

anchors.centerIn:parent

}

Label{

anchors{bottom:hw.top;bottomMargin:5;

horizontalCenter:hw.horizontalCenter}

text:qsTr("HelloQtQuick")

}

}

Asyoucansee,IspecifiedtheIDoftherootApplicationWindowitemtowindowanddeclaredasignalnamedmenuClicked.Inadditiontothis,thereisanotherMenuIteminthemenufile.ItemitsthemenuClickedsignalofwindow,usingitstextasthe

Page 29: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

parameter.

Now,let'sconnecttheslotintheC++filetothisnewlycreatedQMLsignal.Editthemain.cppfile.

#include<QApplication>

#include<QQmlApplicationEngine>

#include"processor.h"

intmain(intargc,char*argv[])

{

QApplicationapp(argc,argv);

QQmlApplicationEngineengine;

engine.load(QUrl(QStringLiteral("qrc:///main.qml")));

QObject*firstRootItem=engine.rootObjects().first();

ProcessormyProcessor;

QObject::connect(firstRootItem,

SIGNAL(menuClicked(QString)),&myProcessor,

SLOT(onMenuClicked(QString)));

returnapp.exec();

}

TheitemintheQMLfileisaccessedasQObjectinC++anditcouldbecasttoQQuickItem.Fornow,weonlyneedtoconnectitssignal,soQObjectwilldo.

YoumaynoticethatIusedtheold-stylesyntaxoftheconnectstatement.ThisisbecauseQMLisdynamicandtheC++compilercan'tdetecttheexistenceofthesignalintheQMLfile.SincethingsinQMLarecheckedatruntime,itdoesn'tmakesensetousetheoldsyntaxhere.

WhenyourunthisapplicationandnavigatetoFile|ClickMeinthemenubar,you'llseeApplicationOutputinQtCreator:

"ClickMe"

Let'sreviewthisprocessagain.TriggeringtheClickMemenuitemresultedintheemissionofthewindow'ssignalmenuClicked.ThissignalpassedthetextofMenuItem,whichisClickMe,totheslotinC++classProcessor,andtheprocessormyProcessorslotonMenuClickedprintedthestringtotheApplicationOutputpanel.

Page 30: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

SummaryInthischapter,welearnedthefundamentalsofQt,whichincludedstepsforhowtocreateaQtapplication.Then,wehadawalk-throughofbothQtWidgetsandQtQuick,andhowtochangethelayout.Finally,weroundedoffbycoveringanimportantconceptaboutthemechanismofsignalsandslots.

Inthenextchapter,wewillhaveachancetoputthisknowledgeintopracticeandgetstartedonbuildingareal-world,andofcoursecross-platform,Qtapplication.

Page 31: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

Chapter2.BuildingaBeautifulCross-platformClockInthischapter,youwilllearnthatQtisagreattooltobuildcross-platformapplications.AQt/C++clockexampleisusedasademonstrationhere.Thetopicscoveredinthischapter,whicharelistedhere,areessentialforanyreal-worldapplications.Theseareasfollows:

CreatingabasicdigitalclockTweakingthedigitalclockSavingandrestoringsettingsBuildingonUnixplatforms

CreatingabasicdigitalclockIt'stimetocreateanewproject,sowewillcreateaQtWidgetsapplicationnamedFancy_Clock.

NoteWewon'tutilizeanyQtQuickknowledgeinthischapter.

Now,changethewindowtitletoFancyClockoranyothernamethatyoulike.Then,themainwindowUIneedstobetailoredbecausetheclockisdisplayedatthetopofthedesktop.Themenubar,statusbar,andtoolbarareallremoved.Afterthat,weneedtodraganLCDNumberwidgetintocentralWidget.Next,changethelayoutofMainWindowtoLayOutHorizontallyinordertoautoresizethesubwidget.ThelastthingthatneedstobedonetotheUIfileistochangeframeShapetoNoFrameundertheQFramecolumninthepropertyoflcdNumber.Ifyou'vedonethisright,you'llgetaprototypeofadigitalclock,asshownhere:

Page 32: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

InordertoupdatetheLCDnumberdisplayrepeatedly,wehavetomakeuseoftheQTimerclasstosetupatimerthatemitsasignalrepetitively.Inadditiontothis,weneedtocreateaslottoreceivethesignalandtoupdatetheLCDnumberdisplaytothecurrenttime.Thus,theQTimeclassisalsoneeded.ThisishowtheheaderfileofMainWindowmainwindow.hwilllooknow:

#ifndefMAINWINDOW_H

#defineMAINWINDOW_H

#include<QMainWindow>

namespaceUi{

classMainWindow;

}

classMainWindow:publicQMainWindow

{

Q_OBJECT

public:

explicitMainWindow(QWidget*parent=0);

~MainWindow();

private:

Ui::MainWindow*ui;

privateslots:

voidupdateTime();

};

#endif//MAINWINDOW_H

Asyoucansee,theonlymodificationmadehereisthedeclarationofaprivateupdateTimeslot.Asusual,we'resupposedtodefinethisslotinmainwindow.cpp,

Page 33: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

whosecontentispastedhere.NotethatweneedtoincludeQTimerandQTime.

#include<QTimer>

#include<QTime>

#include"mainwindow.h"

#include"ui_mainwindow.h"

MainWindow::MainWindow(QWidget*parent):

QMainWindow(parent),

ui(newUi::MainWindow)

{

ui->setupUi(this);

QTimer*timer=newQTimer(this);

connect(timer,&QTimer::timeout,this,

&MainWindow::updateTime);

timer->start(1000);

updateTime();

}

MainWindow::~MainWindow()

{

deleteui;

}

voidMainWindow::updateTime()

{

QTimecurrentTime=QTime::currentTime();

QStringcurrentTimeText=currentTime.toString("hh:mm");

if(currentTime.second()%2==0){

currentTimeText[2]='';

}

ui->lcdNumber->display(currentTimeText);

}

InsidetheupdateTimeslot,theQTimeclassisusedtodealwiththetime,thatis,theclock.Thisclasscanprovideaccuracyofupto1millisecond,iftheunderlyingoperatingsystemsupportsit.However,QTimehasnothingtodowiththetimezoneordaylightsavingtime.Itis,atleast,sufficientforourlittleclock.ThecurrentTime()functionisastaticpublicfunction,whichisusedtocreateaQTimeobjectthatcontainsthesystem'slocaltime.

AsforthesecondlineoftheupdateTimefunction,weusedthetoStringfunctionprovidedbyQTimetoconvertthetimetoastring,andthensaveditincurrentTimeText.TheargumentsthatarepassedtotoStringareintheformatofthetimestring.ThefulllistofexpressionscanbeobtainedfromQtReferenceDocumentation.Thecoloninthemiddleoftheclockshouldbeflashing,justasinthecaseofarealdigitalclock.Hence,weusedanifstatementtocontrolthis.Thecolonwillvanishwhenthesecond'svalueiseven,anditwillreappearwhenthesecond's

Page 34: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

valueisodd.Here,insidetheifblock,weusedthe[2]operatortogetamodifiablereferenceofthethirdcharacterbecausethisistheonlywaytododirectmodificationstoacharacterinsideastring.Here,thecountingofthecurrentTimeTextstringstartsfrom0.Meanwhile,theat()functionofQStringreturnsaconstantcharacter,whichyouhavenorighttochange.Atlast,thisfunctionwillletlcdNumberdisplaythetimestring.Now,let'sgetbacktotheconstructorofMainWindow.AftertheinitializationoftheUI,thefirstthingitdoesistocreateaQTimerobject.Whycan'tweusealocalvariable?TheanswertothatquestionisbecausethelocalvariableswillbedestroyedaftertheconstructionofMainWindow.Ifthetimerhasgone,there'snowaytotriggerupdateTimerepetitively.Wedon'tuseamembervariablebecausethereisnoneedtoperformthedeclarationworkintheheaderfile,sincewewon'tusethistimerelsewhere.

TheQTimerclassisusedtocreatearepetitiveandsingle-shottimer.Itwillemitthetimeoutsignalatconstantintervalsafterstartiscalled.Here,wecreateonetimerandconnectthetimeoutsignaltotheupdateTimeslotsothatupdateTimeiscalledeverysecond.

ThereisanotherimportantaspectinQtcalledparent-childmechanism.Althoughit'snotaswell-knownassignalsandslots,itplaysacrucialroleinthedevelopmentoftheQtapplications.Basicallyspeaking,whenwecreateanQObjectchildwithaparentorexplicitlysetaparentbycallingsetParent,theparentwilladdthisQObjectchildtoitslistofchildren.Then,whentheparentisdeleted,it'llgothroughitslistofchildrenanddeleteeachchild.Inmostcases,especiallyinthedesignofaUI,theparent-childrelationshipissetupimplicitly.Theparentwidgetorlayoutautomaticallybecomestheparentobjecttoitschildrenwidgetsorlayouts.Inothercases,wehavetoexplicitlysettheparentforaQObjectchildsothattheparentcantakeoveritsownershipandmanagethereleaseofitsmemory.Hence,wepasstheQObjectparent,whichisthis,aMainWindowclasstotheconstructorofQTimer.ThisensuresthatQTimerwillbedeletedafterMainWindowisdeleted.That'swhywedon'thavetoexplicitlywritethedeletestatementsinthedestructor.

Attheendoftheconstructor,weneedtocallupdateTimeexplicitly,whichwillallowtheclocktodisplaythecurrenttime.Ifwedon'tdothis,theapplicationwilldisplayazeroforaseconduntilthetimeoutsignalisemittedbytimer.Now,runyourapplication;itwillbesimilartothefollowingscreenshot:

Page 35: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount
Page 36: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

TweakingthedigitalclockIt'stimetomakethisbasicdigitalclocklookmorebeautiful.Let'saddsomethinglikeatransparentbackground,whichsitsontopoftheframelesswindow.Usingatransparentbackgroundcandeliverafantasticvisualeffect.Whiletheframelesswindowhideswindowdecorations,includingaborderandthetitlebar,adesktopwidget,suchasaclock,shouldbeframelessanddisplayedontopofthedesktop.

Tomakeourclocktranslucent,simplyaddthefollowinglinetotheconstructorofMainWindow:

setAttribute(Qt::WA_TranslucentBackground);

TheeffectoftheWA_TranslucentBackgroundattributedependsonthecompositionmanagersontheX11platforms.

Awidgetmayhavelotsofattributes,andthisfunctionisusedtoswitchonorswitchoffaspecifiedattribute.It'sturnedonbydefault.YouneedtopassafalseBooleanasthesecondargumenttodisableanattribute.ThefulllistofQt::WidgetAttributecanbefoundintheQtReferenceDocumentation.

Now,addthefollowinglinetotheconstructoraswell,whichwillmaketheclocklookframelessandmakeitstayontopofthedesktop:

setWindowFlags(Qt::WindowStaysOnTopHint|

Qt::FramelessWindowHint);

Similarly,Qt::WindowFlagsisusedtodefinethetypeofwidget.Itcontrolsthebehaviorofthewidget,ratherthanofitsproperties.Thus,twohintsaregiven:oneistostayontopandtheotheristobeframeless.Ifyouwanttopreserveoldflagswhilesettingnewones,youneedtoaddthemtothecombination.

setWindowFlags(Qt::WindowStaysOnTopHint|

Qt::FramelessWindowHint|windowFlags());

Here,thewindowFlagsfunctionisusedtoretrievethewindowflags.OnethingyoumaybeinterestedtoknowisthatsetWindowFlagswillresultintheinvisibilityofthewidgetaftertheshowfunction.So,youcaneithercallsetWindowFlagsbeforetheshowfunctionofthewindoworwidgetorcallshowagainaftersetWindowFlags.

Afterthemodificationtotheconstructor,thisishowtheclockisexpectedtolook:

Page 37: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

Thereisausefultrickthatyoucanusetohidetheclockfromthetaskbar.Ofcourse,aclockdoesn'tneedtobedisplayedamongtheapplicationsinataskbar.YoushouldneversetaflagsuchasQt::ToolorQt::ToolTipalonetoachievethisbecausethiswillcausetheexitbehavioroftheapplicationtobeabnormal.Thistrickisevensimpler;hereisthecodeofmain.cpp:

#include"mainwindow.h"

#include<QApplication>

intmain(intargc,char*argv[])

{

QApplicationa(argc,argv);

QWidgetwid;

MainWindoww(&wid);

w.show();

returna.exec();

}

TheprecedingcodemakesourMainWindowwobjectachildofQWidgetwid.Thechildwidgetswon'tdisplayonthetaskbarbecausethereshouldbeonlyonetopparentwidget.Meanwhile,ourparentwidget,wid,doesn'tevenshow.It'stricky,butit'stheonlyonethatdoesthetrickwithoutbreakinganyotherlogic.

Well,anewproblemhasjustsurfaced.TheclockisunabletomoveandtheonlywaytocloseitisbystoppingitthroughtheQtCreator'spanelorthroughakeyboard

Page 38: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

shortcut.Thisisbecausewedeclareditasaframelesswindow,whichledtoaninabilitytocontrolitviaawindowmanager.Sincethereisnowaytointeractwithit,it'simpossibletocloseitbyitself.Hence,thesolutiontothisproblemistowriteourownfunctionstomoveandclosetheclock.

Closingthisapplicationmaybemoreurgent.Let'sseehowtoreimplementsomefunctionstoachievethisgoal.First,weneedtodeclareanewshowContextMenuslottodisplayacontextmenuandreimplementmouseReleaseEvent.Thefollowingcodeshowsthecontentofmainwindow.h:

#ifndefMAINWINDOW_H

#defineMAINWINDOW_H

#include<QMainWindow>

namespaceUi{

classMainWindow;

}

classMainWindow:publicQMainWindow

{

Q_OBJECT

public:

explicitMainWindow(QWidget*parent=0);

~MainWindow();

private:

Ui::MainWindow*ui;

privateslots:

voidupdateTime();

voidshowContextMenu(constQPoint&pos);

protected:

voidmouseReleaseEvent(QMouseEvent*);

};

#endif//MAINWINDOW_H

Therearetwonewclassesdefinedintheprecedingcode:QPointandQMouseEvent.TheQPointclassdefinesapointintheplanebyusingintegerprecision.Relatively,thereisanotherclassnamedQPointF,whichprovidesfloatprecision.Well,theQMouseEventclassinheritsQEventandQInputEvent.Itcontainssomeparametersthatdescribeamouseevent.Let'sseewhyweneedtheminmainwindow.cpp:

#include<QTimer>

#include<QTime>

#include<QMouseEvent>

#include<QMenu>

#include<QAction>

Page 39: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

#include"mainwindow.h"

#include"ui_mainwindow.h"

MainWindow::MainWindow(QWidget*parent):

QMainWindow(parent),

ui(newUi::MainWindow)

{

ui->setupUi(this);

setAttribute(Qt::WA_TranslucentBackground);

setWindowFlags(Qt::WindowStaysOnTopHint|

Qt::FramelessWindowHint|windowFlags());

connect(this,&MainWindow::customContextMenuRequested,this,

&MainWindow::showContextMenu);

QTimer*timer=newQTimer(this);

connect(timer,&QTimer::timeout,this,

&MainWindow::updateTime);

timer->start(1000);

updateTime();

}

MainWindow::~MainWindow()

{

deleteui;

}

voidMainWindow::updateTime()

{

QTimecurrentTime=QTime::currentTime();

QStringcurrentTimeText=currentTime.toString("hh:mm");

if(currentTime.second()%2==0){

currentTimeText[2]='';

}

ui->lcdNumber->display(currentTimeText);

}

voidMainWindow::showContextMenu(constQPoint&pos)

{

QMenucontextMenu;

contextMenu.addAction(QString("Exit"),this,SLOT(close()));

contextMenu.exec(mapToGlobal(pos));

}

voidMainWindow::mouseReleaseEvent(QMouseEvent*e)

{

if(e->button()==Qt::RightButton){

emitcustomContextMenuRequested(e->pos());

}

else{

QMainWindow::mouseReleaseEvent(e);

}

}

Page 40: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

NotethatyoushouldincludeQMouseEvent,QMenu,andQActioninordertoutilizetheseclasses.ThereisapredefinedcustomContextMenuRequestedsignal,whichiscoupledwiththenewlycreatedshowContextMenuslot.Forthesakeofconsistency,wewillfollowtherulethatQtdefined,whichmeansthattheQPointargumentincustomContextMenuRequestedshouldbealocalpositioninsteadofaglobalposition.That'swhyweneedamapToGlobalfunctiontotranslatepostoaglobalposition.AsfortheQMenuclass,itprovidesamenuwidgetforamenubar,contextmenu,orotherpop-upmenus.So,wecreatethecontextMenuobject,andthenaddanewactionwiththeExittext.ThisiscoupledwithacloseslotofMainWindow.ThelaststatementisusedtoexecutethecontextMenuobjectatthespecifiedglobalposition.Inotherwords,thisslotwilldisplayapop-upmenuatthegivenposition.

ThereimplementationofmouseReleaseEventisdonetocheckthetriggeredbuttonoftheevent.Ifit'stherightbutton,emitthecustomContextMenuRequestedsignalwiththelocalpositionofthemouse.Otherwise,simplycallthedefaultmouseReleaseEventfunctionofQMainWindow.

Makeuseofthedefaultmemberfunctionsofthebaseclasswhenyoureimplementit.

Runtheapplicationagain;youcanquitbyright-clickingonitandthenselectingExit.Now,weshouldcontinuethereimplementationtomaketheclockmovable.Thistime,weneedtorewritetwoprotectedfunctions:mousePressEventandmouseMoveEvent.Therefore,thisishowtheheaderfilelooks:

#ifndefMAINWINDOW_H

#defineMAINWINDOW_H

#include<QMainWindow>

namespaceUi{

classMainWindow;

}

classMainWindow:publicQMainWindow

{

Q_OBJECT

public:

explicitMainWindow(QWidget*parent=0);

~MainWindow();

private:

Ui::MainWindow*ui;

QPointm_mousePos;

privateslots:

voidupdateTime();

voidshowContextMenu(constQPoint&pos);

Page 41: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

protected:

voidmouseReleaseEvent(QMouseEvent*);

voidmousePressEvent(QMouseEvent*);

voidmouseMoveEvent(QMouseEvent*);

};

#endif//MAINWINDOW_H

Thereisalsoadeclarationofanewprivatemembervariableintheprecedingcode,m_mousePos,whichisaQPointobjectusedtostorethelocalpositionofthemouse.ThefollowingcodedefinesmousePressEventandmouseMoveEvent:

voidMainWindow::mousePressEvent(QMouseEvent*e)

{

m_mousePos=e->pos();

}

voidMainWindow::mouseMoveEvent(QMouseEvent*e)

{

this->move(e->globalPos()-m_mousePos);

}

It'seasierthanyouthought.Whenamousebuttonispressed,thelocalpositionofthemouseisstoredasm_mousePos.Whenthemouseismoving,wecallthemovefunctiontomoveMainWindowtoanewposition.Becausethepositionpassedtomoveisaglobalposition,weneedtouseglobalPosoftheeventminusthelocalpositionofthemouse.Confused?Them_mousePosvariableisthemouse'srelativepositiontothetop-leftpointoftheparentwidget,whichisMainWindowinourcase.Themovefunctionwillmovethetop-leftpointofMainWindowtothegivenglobalposition.Whilethee->globalPos()functionistheglobalpositionofthemouseandnotMainWindow,weneedtosubtracttherelativepositionofm_mousePostotranslatethemouse'sglobalpositiontothetop-leftpointpositionofMainWindow.Afterallthiseffort,theclockshouldlookmuchmoresatisfying.

Page 42: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

SavingandrestoringsettingsAlthoughtheclockcanbemoved,itwon'trestoreitslastpositionafterrestarting.Inadditiontothis,wecangiveuserssomechoicestoadjusttheclock'sappearance,suchasthefontcolor.Tomakeitwork,weneedtheQSettingsclass,whichprovidesplatform-independentpersistentsettings.Itneedsacompanyororganizationnameandthenameofanapplication.AtypicalQSettingsobjectcanbeconstructedbyusingthisline:

QSettingssettings("Qt5Blueprints","FancyClock");

Here,Qt5Blueprintsistheorganization'snameandFancyClockistheapplication'sname.

ThesettingsarestoredinthesystemregistryonWindows,whiletheyarestoredintheXMLpreferencesfilesonMacOSXandtheINItextfilesontheotherUnixoperatingsystems,suchasLinux.However,wedonotusuallyneedtobeconcernedwiththis,sinceQSettingsprovideshigh-levelinterfacestomanipulatethesettings.

Ifwe'regoingtoreadand/orwritesettingsinmultipleplaces,we'dbettersettheorganizationandapplicationinQCoreApplication,whichisinheritedbyQApplication.Themain.cppfile'scontentisshownasfollows:

#include"mainwindow.h"

#include<QApplication>

intmain(intargc,char*argv[])

{

QApplicationa(argc,argv);

a.setOrganizationName(QString("Qt5Blueprints"));

a.setApplicationName(QString("FancyClock"));

QWidgetwid;

MainWindoww(&wid);

w.show();

returna.exec();

}

ThisenablesustousethedefaultQSettingsconstructortoaccessthesamesettings.InordertosavethegeometryandstateofMainWindow,weneedtoreimplementcloseEvent.First,weneedtodeclarecloseEventtobeaprotectedmemberfunction,asfollows:

Page 43: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

voidcloseEvent(QCloseEvent*);

Then,let'sdefinethecloseEventfunctioninmainwindow.cpp,asfollows:

voidMainWindow::closeEvent(QCloseEvent*e)

{

QSettingssts;

sts.setValue("MainGeometry",saveGeometry());

sts.setValue("MainState",saveState());

e->accept();

}

Remembertoadd#include<QSettings>inordertoincludetheQSettingsheaderfiles.

ThankstosetOrganizationNameandsetApplicationName,wedon'tneedtopassanyargumentstotheQSettingsconstructornow.Instead,wecallasetValuefunctiontosavethesettings.ThesaveGeometry()andsaveState()functionsreturntheMainWindowgeometryandstaterespectivelyastheQByteArrayobjects.

Thenextstepistoreadthesesettingsandrestorethegeometryandstate.ThiscanbedoneinsidetheconstructorofMainWindow.Youjustneedtoaddtwostatementstoit:

QSettingssts;

restoreGeometry(sts.value("MainGeometry").toByteArray());

restoreState(sts.value("MainState").toByteArray());

Here,toByteArray()cantranslatethestoredvaluetoaQByteArrayobject.Howdowetesttoseeifthisworks?Todothis,performthefollowingsteps:

1. Rebuildthisapplication.2. Runit.3. Moveitsposition.4. Closeit.5. Runitagain.

You'llseethattheclockwillappearatexactlythesamepositionasitwasbeforeitclosed.Nowthatyou'reprettymuchfamiliarwithwidgets,layouts,settings,signals,andslots,it'stimetocookapreferencedialogbyperformingthefollowingsteps:

1. Right-clickontheFancy_ClockprojectintheProjectspanel.2. SelectAddNew….3. SelectQtintheFilesandClassespanel.4. ClickonQtDesignerFormClassinthemiddlepanel.

Page 44: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

5. SelectDialogwithButtonsBottom.6. FillinPreferenceunderClassname.7. ClickonNext,andthenselectFinish.

QtCreatorwillredirectyoutotheDesignmode.First,let'schangewindowTitletoPreference,andthendosomeUIwork.Performthefollowingstepstodothis:

1. DragLabeltoQDialogandchangeitsobjectNamepropertytocolourLabel.Next,changeitstexttoColour.

2. AddQComboBoxandchangeitsobjectNamepropertytocolourBox.3. AddtheBlack,White,Green,andReditemstocolourBox.4. ChangethelayoutofPreferencetoLayOutinaFormLayOut.

ClosethisUIfile.Gobacktoeditingthepreference.haddaprivateonAcceptedslot.Thefollowingcodeshowsthecontentofthisfile:

#ifndefPREFERENCE_H

#definePREFERENCE_H

#include<QDialog>

namespaceUi{

classPreference;

}

classPreference:publicQDialog

{

Q_OBJECT

public:

explicitPreference(QWidget*parent=0);

~Preference();

private:

Ui::Preference*ui;

privateslots:

voidonAccepted();

};

#endif//PREFERENCE_H

Asusual,wedefinethisslotinthesourcefile.Besides,wehavetosetupsomeinitializationsintheconstructorofPreference.Thus,preference.cppbecomessimilartothefollowingcode:

#include<QSettings>

#include"preference.h"

#include"ui_preference.h"

Page 45: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

Preference::Preference(QWidget*parent):

QDialog(parent),

ui(newUi::Preference)

{

ui->setupUi(this);

QSettingssts;

ui->colourBox->setCurrentIndex(sts.value("Colour").toInt());

connect(ui->buttonBox,&QDialogButtonBox::accepted,this,

&Preference::onAccepted);

}

Preference::~Preference()

{

deleteui;

}

voidPreference::onAccepted()

{

QSettingssts;

sts.setValue("Colour",ui->colourBox->currentIndex());

}

Similarly,weloadthesettingsandchangethecurrentitemofcolourBox.Then,it'sthesignalandslotcouplingthatfollow.NotethatQtCreatorhasautomaticallygeneratedtheacceptandrejectconnectionsbetweenbuttonBoxandPreferenceforus.TheacceptedsignalofbuttonBoxisemittedwhentheOKbuttonisclicked.Likewise,therejectedsignalisemittediftheuserclicksonCancel.YoumaywanttocheckSignals&SlotsEditorintheDesignmodetoseewhichconnectionsaredefinedthere.Thisisshowninthefollowingscreenshot:

AsforthedefinitionoftheonAcceptedslot,itsavescurrentIndexofcolourBoxtothesettingssothatwecanreadthissettingelsewhere.

Page 46: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

Now,whatwe'regoingtodonextisaddanentryforPreferenceinthepop-upmenuandchangethecoloroflcdNumberaccordingtotheColoursettingvalue.Therefore,youshoulddefineaprivateslotandaprivatememberfunctioninmainwindow.hfirst.

#ifndefMAINWINDOW_H

#defineMAINWINDOW_H

#include<QMainWindow>

namespaceUi{

classMainWindow;

}

classMainWindow:publicQMainWindow

{

Q_OBJECT

public:

explicitMainWindow(QWidget*parent=0);

~MainWindow();

private:

Ui::MainWindow*ui;

QPointm_mousePos;

voidsetColour();

privateslots:

voidupdateTime();

voidshowContextMenu(constQPoint&pos);

voidshowPreference();

protected:

voidmouseReleaseEvent(QMouseEvent*);

voidmousePressEvent(QMouseEvent*);

voidmouseMoveEvent(QMouseEvent*);

voidcloseEvent(QCloseEvent*);

};

#endif//MAINWINDOW_H

ThesetColourfunctionisusedtochangethecoloroflcdNumber,whiletheshowPreferenceslotwillexecuteaPreferenceobject.Thedefinitionsofthesetwomembersareinthemainwindow.cppfile,whichisdisplayedinthefollowingmanner:

#include<QTimer>

#include<QTime>

#include<QMouseEvent>

#include<QMenu>

#include<QAction>

#include<QSettings>

#include"mainwindow.h"

#include"preference.h"

Page 47: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

#include"ui_mainwindow.h"

MainWindow::MainWindow(QWidget*parent):

QMainWindow(parent),

ui(newUi::MainWindow)

{

ui->setupUi(this);

setAttribute(Qt::WA_TranslucentBackground);

setWindowFlags(Qt::WindowStaysOnTopHint|

Qt::FramelessWindowHint|windowFlags());

QSettingssts;

restoreGeometry(sts.value("MainGeometry").toByteArray());

restoreState(sts.value("MainState").toByteArray());

setColour();

connect(this,&MainWindow::customContextMenuRequested,this,

&MainWindow::showContextMenu);

QTimer*timer=newQTimer(this);

connect(timer,&QTimer::timeout,this,

&MainWindow::updateTime);

timer->start(1000);

updateTime();

}

MainWindow::~MainWindow()

{

deleteui;

}

voidMainWindow::updateTime()

{

QTimecurrentTime=QTime::currentTime();

QStringcurrentTimeText=currentTime.toString("hh:mm");

if(currentTime.second()%2==0){

currentTimeText[2]='';

}

ui->lcdNumber->display(currentTimeText);

}

voidMainWindow::showContextMenu(constQPoint&pos)

{

QMenucontextMenu;

contextMenu.addAction(QString("Preference"),this,

SLOT(showPreference()));

contextMenu.addAction(QString("Exit"),this,SLOT(close()));

contextMenu.exec(mapToGlobal(pos));

}

voidMainWindow::mouseReleaseEvent(QMouseEvent*e)

{

if(e->button()==Qt::RightButton){

Page 48: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

emitcustomContextMenuRequested(e->pos());

}

else{

QMainWindow::mouseReleaseEvent(e);

}

}

voidMainWindow::mousePressEvent(QMouseEvent*e)

{

m_mousePos=e->pos();

}

voidMainWindow::mouseMoveEvent(QMouseEvent*e)

{

this->move(e->globalPos()-m_mousePos);

}

voidMainWindow::closeEvent(QCloseEvent*e)

{

QSettingssts;

sts.setValue("MainGeometry",saveGeometry());

sts.setValue("MainState",saveState());

e->accept();

}

voidMainWindow::setColour()

{

QSettingssts;

inti=sts.value("Colour").toInt();

QPalettec;

switch(i){

case0://black

c.setColor(QPalette::Foreground,Qt::black);

break;

case1://white

c.setColor(QPalette::Foreground,Qt::white);

break;

case2://green

c.setColor(QPalette::Foreground,Qt::green);

break;

case3://red

c.setColor(QPalette::Foreground,Qt::red);

break;

}

ui->lcdNumber->setPalette(c);

this->update();

}

voidMainWindow::showPreference()

{

Preference*pre=newPreference(this);

pre->exec();

setColour();

}

Page 49: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

WecallsetColourintheconstructorinordertosetthecoloroflcdNumbercorrectly.InsidesetColour,wefirstreadtheColourvaluefromthesettings,andthenuseaswitchstatementtogetthecorrectQPaletteclassbeforecallingsetPalettetochangethecoloroflcdNumber.SinceQtdoesn'tprovideadirectwaytochangetheforegroundcoloroftheQLCDNumberobjects,weneedtousethistediousmethodtoachievethis.Attheendofthismemberfunction,wecallupdate()toupdatetheMainWindowuserinterface.

NoteDon'tforgettoaddthePreferenceactiontocontextMenuinsideshowContextMenu.Otherwise,therewillbenowaytoopenthedialog.

IntherelevantshowPreferenceslot,wecreateanewPreferenceobject,whichisthechildofMainWindow,andthencallexec()toexecuteandshowit.Lastly,wecallsetColour()tochangethecoloroflcdNumber.AsPreferenceismodalandexec()hasitsowneventloop,itwillblocktheapplicationuntilpreisfinished.Afterprefinishesexecuting,eitherbyacceptedorrejected,setColourwillbecallednext.Ofcourse,youcanusethesignal-slotwaytoimplementit,butwehavetoapplysomemodificationstothepreviouscode.Firstly,deletetheaccepted-acceptsignal-slotcoupleinpreference.uiintheDesignmode.Then,addaccept()totheendofonAcceptedinpreference.cpp.

voidPreference::onAccepted()

{

QSettingssts;

sts.setValue("Colour",ui->colourBox->currentIndex());

this->accept();

}

Now,showPreferenceinmainwindow.cppcanberewrittenasfollows:

voidMainWindow::showPreference()

{

Preference*pre=newPreference(this);

connect(pre,&Preference::accepted,this,

&MainWindow::setColour);

pre->exec();

}

TipTheconnectstatementshouldn'tbeplacedafterexec(),asitwillcausethe

Page 50: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

bindingtofail.

Nomatterwhichwayyouprefer,theclockshouldhaveaPreferencedialognow.Runit,selectPreferencefromthepop-upmenu,andchangethecolortowhateveryouplease.Youshouldexpectaresultsimilartowhatisshowninthefollowingscreenshot:

Page 51: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

BuildingontheUnixplatformsSofar,wearestilltrappedwithourapplicationsonWindows.It'stimetotestwhetherourcodecanbebuiltonotherplatforms.Inthischapter,thecodeinvolvedwithonlydesktopoperatingsystems,whilewe'llgetachancetobuildapplicationsformobileplatformslaterinthisbook.Intermsofotherdesktopoperatingsystems,thereareplentyofthem,andmostofthemareUnix-like.QtofficiallysupportsLinuxandMacOSX,alongwithWindows.Hence,usersofothersystems,suchasFreeBSD,mayneedtocompileQtfromscratchorgetprebuiltpackagesfromtheirowncommunities.Inthisbook,theLinuxdistributionFedora20isusedasademonstrationtointroduceplatformcrossing.PleasebearinmindthattherearelotsofdesktopenvironmentsandthemingtoolsonLinux,sodon'tbesurprisediftheuserinterfacediffers.Well,sinceyou'recurious,letmetellyouthatthedesktopenvironmentisKDE4withQtCurve,unifyingGTK+/Qt4/Qt5inmycase.Let'sgetstartedassoonasyou'reready.Youcanperformthefollowingstepstodothis:

1. CopythesourcecodeofFancyClocktoadirectoryunderLinux.2. DeletetheFancy_Clock.pro.userfile.3. OpenthisprojectinQtCreator.

Now,buildandrunthisapplication.Everythingisgoodexceptthatthere'sataskbaricon.Smallissuessuchasthiscan'tbeavoidedwithouttesting.Well,tofixthis,justmodifyasinglelineintheconstructorofMainWindow.Changingthewindowflagswillamendthis:

setWindowFlags(Qt::WindowStaysOnTopHint|

Qt::FramelessWindowHint|Qt::Tool);

Ifyourunthefileagain,FancyClockwon'tshowupinthetaskbaranymore.PleasekeeptheMainWindowobject,w,asachildofQWidgetwid;otherwise,theapplicationwon'tterminateafteryouclickonClose.

NotethatthePreferencedialogusesnativeUIcontrols,ratherthanbringingtheotherplatform'scontrolstothisone.ThisisoneofthemostfascinatingthingsthatQthasprovided.AlltheQtapplicationswilllookandbehavelikenativeapplicationsacrossallplatforms.

Page 52: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

It'snotahustlebutthetruthisthatonceyoucodetheQtapplication,youcanruniteverywhere.Youdon'tneedtowritedifferentGUIsfordifferentplatforms.Thatdarkagehaslonggone.However,youmaywanttowritesomefunctionsforspecificplatforms,eitherbecauseofparticularneedsorworkarounds.Firstly,I'dliketointroduceyoutosomeQtAdd-Onmodulesdedicatedforseveralplatforms.

TakeQtWindowsExtrasasanexample.SomecoolfeaturesthatWindowsprovides,suchasThumbnailToolbarandAeroPeek,aresupportedbyQtthroughthisadd-onmodule.

Well,addingthismoduletotheprojectfiledirectly,whichinthiscaseisFancy_Clock.profile,willdefinitelyupsetotherplatforms.Abetterwaytodothisistotestwhetherit'sonWindows;ifso,addthismoduletotheproject.Otherwise,skipthisstep.ThefollowingcodeshowsyoutheFancy_Clock.profile,whichwilladdthewinextrasmoduleifit'sbuiltonWindows:

QT+=coregui

win32:QT+=winextras

greaterThan(QT_MAJOR_VERSION,4):QT+=widgets

TARGET=Fancy_Clock

TEMPLATE=app

SOURCES+=main.cpp\

mainwindow.cpp\

preference.cpp

HEADERS+=mainwindow.h\

preference.h

FORMS+=mainwindow.ui\

preference.ui

Asyoucansee,win32isaconditionalstatement,whichistrueonlyifthehostmachineisWindows.Afteraqmakererunforthisproject,you'llbeabletoincludeand

Page 53: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

utilizethoseextraclasses.

Similarly,ifyouwanttodosomethingontheUnixplatforms,simplyusethekeywordunix,butunixwillbetrueonlyonLinux/X11orMacOSX.TodistinguishMacOSXfromLinux,here'sanexample:

win32{

message("BuiltonWindows")

}

else:unix:macx{

message("BuiltonMacOSX")

}

else{

message("BuiltonLinux")

}

Infact,youcanjustuseunix:!macxastheconditionalstatementtodosomeplatform-specificworkonLinux.It'sacommonpracticetohavemanyplatform-specificstatementsintheprojectfile(s),especiallywhenyourprojectneedstobelinkedwithotherlibraries.Youhavetospecifydifferentpathsfortheselibrariesondifferentplatforms,otherwisethecompilerwillcomplainaboutmissinglibrariesorunknownsymbols.

Inadditiontothis,youmaywanttoknowhowtowriteplatform-specificcodewhilekeepingitfromotherplatforms.SimilartoC++,it'sapredefinedmacrothatishandledbyvariouscompilers.However,thesecompilermacrolistsmaydifferfromonecompilertoanother.So,itisbettertouseGlobalQtDeclarationsinstead.I'lluseathefollowingshortexampletoexplainthisfurther:

voidMainWindow::showContextMenu(constQPoint&pos)

{

QMenucontextMenu;

#ifdefQ_OS_WIN

contextMenu.addAction(QString("Options"),this,

SLOT(showPreference()));

#elifdefined(Q_OS_LINUX)

contextMenu.addAction(QString("Profile"),this,

SLOT(showPreference()));

#else

contextMenu.addAction(QString("Preference"),this,

SLOT(showPreference()));

#endif

contextMenu.addAction(QString("Exit"),this,SLOT(close()));

contextMenu.exec(mapToGlobal(pos));

}

TheprecedingcodeshowsyouthenewversionofshowContextMenu.ThePreferencemenuentrywillusedifferenttextsondifferentplatforms,namelyWindows,Linux,and

Page 54: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

MacOSX.ChangeyourshowContextMenufunctionandrunitagain.You'llseeOptionsonWindows,ProfileonLinux,andPreferenceonMacOSX.Belowisalistconcerningtheplatform-specificmacros.Youcangetafulldescription,includingothermacros,functions,andtypesontheQtGlobaldocument.

Macro CorrespondPlatform

Q_OS_ANDROID Android

Q_OS_FREEBSD FreeBSD

Q_OS_LINUX Linux

Q_OS_IOS iOS

Q_OS_MAC MacOSXandiOS(Darwin-based)

Q_OS_WIN AllWindowsplatforms,includingWindowsCE

Q_OS_WINPHONE WindowsPhone8

Q_OS_WINRT WindowsRuntimeonWindows8.WindowsRTandWindowsPhone8

Page 55: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

SummaryInthischapter,information,includingsometricks,aboutUIdesigningisincluded.Furthermore,therearebasicyetusefulcross-platformtopics.Now,you'reabletowriteanelegantQtapplicationinyourfavorite,andpossiblyalreadymastered,C++.

Inthenextchapter,wearegoingtolearnhowtowriteanapplicationinQtQuick.However,fearnot;QtQuickiseveneasierand,ofcourse,quickertodevelop.

Page 56: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

Chapter3.CookinganRSSReaderwithQtQuickInthischapter,wewillfocusondevelopingapplicationswithQtQuick.Fortouchscreen-enableddevices,QtQuickapplicationsaremuchmoreresponsiveandeasytowrite.AnRSSreaderisusedasademonstrationinthischapter.ThefollowingtopicswillenableyoutobuildelegantQtQuickapplications:

UnderstandingmodelandviewParsingRSSFeedsbyXmlListModelTweakingthecategoriesUtilizingScrollViewAddingBusyIndicatorMakingaframelesswindowDebuggingQML

UnderstandingmodelandviewAsmentionedbefore,QtQuickapplicationsaredifferentfromtraditionalQtWidgetsapplications.YouaregoingtowriteQMLinsteadofC++code.So,let'screateanewproject,aQtQuickapplicationnamedRSS_Reader.Thistime,wewilluseQtQuick2.3asthecomponentset.Sincewewon'tusethewidgetsprovidedbyQtQuickControls,we'llwriteourownwidgets.

Beforegettingourhandsdirty,let'ssketchoutwhatthisapplicationlookslike.Accordingtothefollowingdiagram,therewillbetwosections.Theleft-handpanelprovidessomecategoriessothatuserscanchooseinterestingcategories.Theright-handpanelisthemainarea,whichdisplaysnewsunderthecurrentcategory.ThisisatypicalRSSnewsreader'suserinterface.

Page 57: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

WecanimplementtheCategoriespanelbyusingListView.Thistype(wesay"type"insteadof"class"inQML)isusedtodisplaydatafromallsortsoflistmodels.Solet'seditourmain.qmltosomethingsimilartothis:

importQtQuick2.3

importQtQuick.Window2.2

Window{

id:mainWindow

visible:true

width:720

height:400

ListView{

id:categories

width:150

height:parent.height

orientation:ListView.Vertical

anchors.top:parent.top

spacing:3

}

}

ListViewneedsamodeltogetdatafrom.Inthiscase,wecanutilizeListModelforitssimplicity.Toachievethis,let'screateanewFeeds.qmlfile,whichwillcontainacustomListModelexample:

1. Right-clickontheproject.2. SelectAddNew….3. NavigatetoQt|QMLFile(QtQuick2).4. EntertheFeeds.qmlfilename.

HereisthecontentofFeeds.qml:

Page 58: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

importQtQuick2.3

ListModel{

ListElement{name:"TopStories";url:

"http://feeds.bbci.co.uk/news/rss.xml"}

ListElement{name:"World";url:

"http://feeds.bbci.co.uk/news/world/rss.xml"}

ListElement{name:"UK";url:

"http://feeds.bbci.co.uk/news/uk/rss.xml"}

ListElement{name:"Business";url:

"http://feeds.bbci.co.uk/news/business/rss.xml"}

ListElement{name:"Politics";url:

"http://feeds.bbci.co.uk/news/politics/rss.xml"}

ListElement{name:"Health";url:

"http://feeds.bbci.co.uk/news/health/rss.xml"}

ListElement{name:"Education&Family";url:

"http://feeds.bbci.co.uk/news/education/rss.xml"}

ListElement{name:"Science&Environment";url:

"http://feeds.bbci.co.uk/news/science_and_environment/rss.xml"

}

ListElement{name:"Technology";url:

"http://feeds.bbci.co.uk/news/technology/rss.xml"}

ListElement{name:"Entertainment&Arts";url:

"http://feeds.bbci.co.uk/news/entertainment_and_arts/rss.xml"

}

}

NoteWeuseBBCNewsRSSasfeeds,butyoumaywishtochangeittoanother.

Asyoucansee,theprecedingListModelexamplehastworoles,nameandurl.A"role"isbasicallyafancywayofsayingthechilditem.ThesecanbeboundtobytheListViewdelegatethatweareabouttocreate.Inthisway,rolesusuallyrepresentthepropertiesofanentityorcolumnsofatable.

Letmeexplaintherelationbetweenview,model,anddelegate,whichisanotherimportantyetdifficultconceptintheworldofQt.Thisisofficiallycalledmodel-viewarchitecture.Inadditiontothetraditionalview,Qtdecouplestheviewandcontrollersothatthedatacanberenderedandeditedinmanycustomizedways.Thelatterismuchmoreelegantandefficient.Thefollowingdiagramhelpsyouunderstandthisconcept:

Page 59: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

TakeListModel,whichisamodelusedtoarrangedata,asanexampletoelaboratetherelationship.CategoriesDelegate,showninthefollowingcode,isadelegateandisusedtocontrolhowtodisplaytherolesfromthemodel.Lastly,weuseaview,whichisListViewinthiscase,torenderthedelegate.

Thecommunicationbetweenthemodels,views,anddelegatesarebasedonthesignalsandslotsmechanism.It'lltakeyousometimetofullyunderstandthisconcept.Hopefully,wecanshortenthistimebypracticingthisexample.Atthisstage,wealreadyhaveaviewandamodel.Wehavetodefineadelegate,whichisCategoriesDelegateasmentionedbefore,tocontrolthedatafromthemodelandrenderitontheview.AddanewCategoriesDelegate.qmlfile,whosecontentispastedinthisway:

importQtQuick2.3

Rectangle{

id:delegate

propertyrealitemWidth

width:itemWidth

height:80

Text{

id:title

anchors{left:parent.left;leftMargin:10;right:

parent.right;rightMargin:10}

anchors.verticalCenter:delegate.verticalCenter

text:name

font{pointSize:18;bold:true}

Page 60: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

verticalAlignment:Text.AlignVCenter

wrapMode:Text.WordWrap

}

}

Youshouldhavesomeideaabouttherelationbetweenthemodel,delegate,andview.Here,weuseRectangleasthedelegatetype.InsidetheRectangletypeisaTextobjectthatdisplaysthenamefromourListModelexample.Asforthefontproperty,hereweusepointSizetospecifythesizeoftext,whileyoucanusepixelSizeasanalternative.

Tofinishthemodel-viewarchitecture,gobacktothemain.qmledit:

importQtQuick2.3

importQtQuick.Window2.2

import"qrc:/"

Window{

id:mainWindow

visible:true

width:720

height:400

Feeds{

id:categoriesModel

}

ListView{

id:categories

width:150

height:parent.height

orientation:ListView.Vertical

anchors.top:parent.top

spacing:3

model:categoriesModel

delegate:CategoriesDelegate{

id:categoriesDelegate

width:categories.width

}

}

}

Takenoteofthethirdline;it'scrucialtoimportthisdirectoryintoqrc.Weuse"qrc:/"becauseweneedtoputtheQMLfilesintherootdirectory.ModifyitifyouuseasubdirectorytokeepFeeds.qmlandCategoriesDelegate.qml.Inthisexample,thesefilesareleftunorganized.Butit'shighlyrecommendedtokeepthemcategorizedasadifferentmodule.Ifyoudidn'timportthedirectory,youwon'tbeabletousetheseQMLfiles.

Page 61: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

InsidetheWindowitem,wecreateFeeds,whichisexactlyanelementofListModelfromFeeds.qml.Then,wegivethisFeedsitemacategoriesModelIDanduseitasthemodelofListView.Specifyingthedelegateisquitesimilartospecifyingthemodelforviews.InsteadofdeclaringitoutsideListView,wehavetodefineitinsidethedelegatescope,otherwisethedelegateitem,CategoriesDelegate,won'tbeabletogetdatafromthemodel.Asyoucansee,wecanmanipulatethewidthofcategoriesDelegate.Thisistoensurethatthetextwon'tlieoutsidetheboundaryofListView.

Ifeverythingisdonecorrectly,clickonRunandyou'llseeitrunlikethis:

Page 62: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

ParsingRSSFeedsbyXmlListModelIt'struethatwenowhavecategories,buttheydon'tseemtobeinvolvedwithRSSatall.Also,ifyoudigdeeper,you'llfindthattheRSSfeedsareinfacttheXMLdocuments.Qtalreadyprovidesausefultypetohelpusparsethem.Wedon'tneedtoreinventthewheel.Thispowerfultypeistheso-calledXmlListModelelementanditusesXmlRoletoquery.

Firstly,weneedtoexposetheurlroleofcategoriesModeltothemainscope.Thisisdonebydeclaringthepropertystoringthemodel'scurrentelement,url,insideListView.Then,wecanaddanXmlListModelelementandusethaturlelementasitssource.Accordingly,themodifiedmain.qmlfileispastedhere:

importQtQuick2.3

importQtQuick.Window2.2

importQtQuick.XmlListModel2.0

import"qrc:/"

Window{

id:mainWindow

visible:true

width:720

height:400

Feeds{

id:categoriesModel

}

ListView{

id:categories

width:150

height:parent.height

orientation:ListView.Vertical

anchors.top:parent.top

spacing:3

model:categoriesModel

delegate:CategoriesDelegate{

id:categoriesDelegate

width:categories.width

}

propertystringcurrentUrl:categoriesModel.get(0).url

}

XmlListModel{

id:newsModel

source:categories.currentUrl

namespaceDeclarations:"declarenamespacemedia=

'http://search.yahoo.com/mrss/';declarenamespaceatom=

'http://www.w3.org/2005/Atom';"

Page 63: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

query:"/rss/channel/item"

XmlRole{name:"title";query:"title/string()"}

XmlRole{name:"description";query:

"description/string()"}

XmlRole{name:"link";query:"link/string()"}

XmlRole{name:"pubDate";query:"pubDate/string()"}

//XPathstartsfrom1not0andthesecondthumbnailis

largerandmoreclear

XmlRole{name:"thumbnail";query:

"media:thumbnail[2]/@url/string()"}

}

}

NoteObjects'valuesarechangeddynamicallyandupdatedimplicitlyinQtQuick.Youdon'tneedtogivenewvaluesexplicitly.

Inordertousethiselement,youwillneedtoimportthemodulebyaddinganimportQtQuick.XmlListModel2.0line.Additionally,XmlListModelisaread-onlymodelwhichmeansthatyoucan'tmodifythedatasourcethroughthismodel.ThisiscompletelyacceptablesincewhatweneedistoretrievethenewsdatafromtheRSSfeeds.TakeTopStoriesasanexample;thefollowingcodeisapartofthisXMLdocumentcontent:

<?xmlversion="1.0"encoding="UTF-8"?>

<?xml-stylesheettitle="XSL_formatting"type="text/xsl"

href="/shared/bsp/xsl/rss/nolsol.xsl"?>

<rssxmlns:media="http://search.yahoo.com/mrss/"

xmlns:atom="http://www.w3.org/2005/Atom"version="2.0">

<channel>

<title>BBCNews-Home</title>

<link>http://www.bbc.co.uk/news/#sa-

ns_mchannel=rss&amp;ns_source=PublicRSS20-sa</link>

<description>ThelateststoriesfromtheHomesectionofthe

BBCNewswebsite.</description>

<language>en-gb</language>

<lastBuildDate>Mon,26Jan201523:19:42GMT</lastBuildDate>

<copyright>Copyright:(C)BritishBroadcastingCorporation,

seehttp://news.bbc.co.uk/2/hi/help/rss/4498287.stmforterms

andconditionsofreuse.</copyright>

<image>

<url>http://news.bbcimg.co.uk/nol/shared/img/bbc_news_120x60.g

if</url>

<title>BBCNews-Home</title>

<link>http://www.bbc.co.uk/news/#sa-

Page 64: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

ns_mchannel=rss&amp;ns_source=PublicRSS20-sa</link>

<width>120</width>

<height>60</height>

</image>

<ttl>15</ttl>

<atom:linkhref="http://feeds.bbci.co.uk/news/rss.xml"

rel="self"type="application/rss+xml"/>

<item>

<title>GermanywarnsGreeceoverdebts</title>

<description>TheGermangovernmentwarnsGreecethatitmust

meetitscommitmentstolenders,aftertheelectionwinofthe

Greekanti-austeritySyrizaparty.</description>

<link>http://www.bbc.co.uk/news/business-30977714#sa-

ns_mchannel=rss&amp;ns_source=PublicRSS20-sa</link>

<guid

isPermaLink="false">http://www.bbc.co.uk/news/business-

30977714</guid>

<pubDate>Mon,26Jan201520:15:56GMT</pubDate>

<media:thumbnailwidth="66"height="49"

url="http://news.bbcimg.co.uk/media/images/80536000/jpg/_80536

447_025585607-1.jpg"/>

<media:thumbnailwidth="144"height="81"

url="http://news.bbcimg.co.uk/media/images/80536000/jpg/_80536

448_025585607-1.jpg"/>

</item>

……

ThenamespaceDeclarationspropertyneedstobesetbecausetheXMLdocumenthastheXMLnamespaces.

<rssxmlns:media="http://search.yahoo.com/mrss/"

xmlns:atom="http://www.w3.org/2005/Atom"version="2.0">

Here,xmlnsstandsfortheXMLnamespace,sowedeclarethenamespaceaccordingly.

namespaceDeclarations:"declarenamespacemedia=

'http://search.yahoo.com/mrss/';declarenamespaceatom=

'http://www.w3.org/2005/Atom';"

Infact,youcanjustdeclareamedianamespaceandsafelyignoreanatomnamespace.However,ifyoudidn'tdeclarethemedianamespace,theapplicationwouldendupfailingtoparsetheXMLdocument.Hence,gobacktoseetheXMLdocumentandyou'llfindithasahierarchytoorderdata.Whatwewantherearetheseitems.Takethetop-levelasroot,/,sothepathofitemcanbewrittenas/rss/channel/item.Thisisexactlywhatweputinquery.

AlltheXmlRoleelementsarecreatedusingqueryasthebase.ForXmlRole,namedefinesitsname,whichdoesn'tneedtobethesameasintheXMLdocument.It's

Page 65: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

similartoidfortheregularQtQuickitems.However,thequeryofXmlRolemustusearelativepathtothequeryofXmlListModel.Althoughit'sastring()typeinmostcases,itstillmustbedeclaredexplicitly.Ifthereareelementssharingthesamekeys,it'dbeanarraywheretheelementlistedfirsthasthefirstindex.

NoteThefirstindexinXPathis1insteadof0.

Sometimes,weneedtogetanattributethumbnail.Thisistheurlattributeofthemedia:thumbnailtag.Inthiscase,it'sthe@symbolthatwilldoallthemagicweneed.

Similartothesecategories,wehavetowriteadelegatefortheXmlListModelelementtorendertheview.ThenewQMLNewsDelegate.qmlfileisshownhere:

importQtQuick2.3

Column{

id:news

spacing:8

//usedtoseparatenewsitem

Item{height:news.spacing;width:news.width}

Row{

width:parent.width

height:children.height

spacing:news.spacing

Image{

id:titleImage

source:thumbnail

}

Text{

width:parent.width-titleImage.width

wrapMode:Text.WordWrap

font.pointSize:20

font.bold:true

text:title

}

}

Text{

width:parent.width

font.pointSize:9

font.italic:true

Page 66: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

text:pubDate+"(<ahref=\""+link+"\">Details</a>)"

onLinkActivated:{

Qt.openUrlExternally(link)

}

}

Text{

width:parent.width

wrapMode:Text.WordWrap

font.pointSize:10.5

horizontalAlignment:Qt.AlignLeft

text:description

}

}

ThedifferenceisthatthistimeweuseColumntoorganizethenewsdataandrepresentitinanintuitiveway.Therelevantdiagramissketchedasfollows:

So,thisiswhyweuseRowinsideColumntoboxThumbnailandTitletogether.Thus,weneedtoputanemptyitemelementinfronttoseparateeachnewsdelegate.Apartfromtheseself-explanatorylines,thereisatipfordealingwithlinks.YouneedtospecifytheslotfortheonLinkActivatedsignal,whichisQt.openUrlExternally(link)inthiscase.Otherwise,nothingwillhappenwhenyouclickonthelink.

Afterallthis,it'stimetowriteaviewinmain.qmltodisplayournews:

importQtQuick2.3

importQtQuick.Window2.2

importQtQuick.XmlListModel2.0

import"qrc:/"

Window{

Page 67: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

id:mainWindow

visible:true

width:720

height:400

Feeds{

id:categoriesModel

}

ListView{

id:categories

width:150

height:parent.height

orientation:ListView.Vertical

anchors.top:parent.top

spacing:3

model:categoriesModel

delegate:CategoriesDelegate{

id:categoriesDelegate

width:categories.width

}

propertystringcurrentUrl:categoriesModel.get(0).url

}

XmlListModel{

id:newsModel

source:categories.currentUrl

namespaceDeclarations:"declarenamespacemedia=

'http://search.yahoo.com/mrss/';declarenamespaceatom=

'http://www.w3.org/2005/Atom';"

query:"/rss/channel/item"

XmlRole{name:"title";query:"title/string()"}

XmlRole{name:"description";query:

"description/string()"}

XmlRole{name:"link";query:"link/string()"}

XmlRole{name:"pubDate";query:"pubDate/string()"}

//XPathstartsfrom1not0andthesecondthumbnailis

largerandmoreclear

XmlRole{name:"thumbnail";query:

"media:thumbnail[2]/@url/string()"}

}

ListView{

id:newsList

anchors{left:categories.right;leftMargin:10;right:

parent.right;rightMargin:4;top:parent.top;bottom:

parent.bottom;}

model:newsModel

delegate:NewsDelegate{

width:newsList.width

}

Page 68: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

}

}

RemembertodefinethewidthofNewsDelegateincaseitdisplaysabnormally.ClickonRun;theapplicationwilllooklikethefollowingscreenshot:

Page 69: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

TweakingthecategoriesThisapplicationisstillincomplete.Forexample,thenewsviewwon'tchangeatallafteryouclickontheothercategories.Inthisstage,we'regoingtoworkthisoutandmakeitmorebeautiful.

WhatweneedtodoisaddMouseAreatoCategoriesDelegate.Thiselementisusedtodealwithavarietyofmouseinteractions,includingclicking.ThenewCategoriesDelegate.qmlfile'scodeispastedhere:

importQtQuick2.3

Rectangle{

id:delegate

height:80

Text{

id:title

anchors{left:parent.left;leftMargin:10;right:

parent.right;rightMargin:10}

anchors.verticalCenter:delegate.verticalCenter

text:name

font{pointSize:18;bold:true}

verticalAlignment:Text.AlignVCenter

wrapMode:Text.WordWrap

}

MouseArea{

anchors.fill:delegate

onClicked:{

categories.currentIndex=index

if(categories.currentUrl==url)

newsModel.reload()

else

categories.currentUrl=url

}

}

}

Asyoucansee,onceadelegategetsclickedon,it'llchangecategories.currentIndexandcurrentUrlifnecessary,orsimplyletnewsModelreload.Asmentionedbefore,QMLisadynamiclanguage,whichchangescategories.currentUrl,thesourcepropertyofnewsModel,andwouldautomaticallycausenewsModeltoreload.

Tohelpusersdistinguishacurrently-selectedcategoryfromothers,wemaywishtochangeitssizeandscale.Therearesomeattachedproperties,whichareattachedtoeachinstanceofadelegateoraresimplysharedamongthem.The.isCurrentItem

Page 70: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

propertyistheonethatwouldsousafavor.It'saBooleanvaluethatholdswhetherthisdelegateisthecurrentitemornot.However,onlytherootitemofadelegatecanaccesstheseattachedpropertiesdirectly.Inordertocodeinacleanway,weaddalinetoRectangleofCategoriesDelegatetoholdthisproperty:

propertyboolselected:ListView.isCurrentItem

Now,wecanutilizeselectedinTextbyaddingthefollowinglinestotheTextitem:

scale:selected?1.0:0.8

color:selected?"#000":"#AAA"

Textwillbescaledto0.8ifit'snotselectedandwillbehaveasusualwhenit'sactive.Asimilarconditionisinplaceforitscolor.The#AAAcolorcodeisanextremelylightgraycolor,whichmakestheactiveblacktextstandoutmore.However,thereisnoanimationforthesechanges.Whilewewantthesetransitionstobemorenatural,QtQuickprovidesBehaviorwithStatetomakethesetransitionshappen.ByaddingtheselinestotheTextitem,wegetthefollowingcode:

Behavioroncolor{ColorAnimation{duration:300}}

Behavioronscale{PropertyAnimation{duration:300}}

Animationsareexpectedtopresentwhenyouchangethecurrentdelegate,whichresultsinchangesinthecolorandscale.Ifyou'renotsurewhetheryou'veperformedthecorrectmodification,thefollowingcodeshowsyouthenewlymodifiedCategoriesDelegate.qmlfile:

importQtQuick2.3

Rectangle{

id:delegate

height:80

propertyboolselected:ListView.isCurrentItem

Text{

id:title

anchors{left:parent.left;leftMargin:10;right:

parent.right;rightMargin:10}

anchors.verticalCenter:delegate.verticalCenter

text:name

font{pointSize:18;bold:true}

verticalAlignment:Text.AlignVCenter

wrapMode:Text.WordWrap

scale:selected?1.0:0.8

color:selected?"#000":"#AAA"

Behavioroncolor{ColorAnimation{duration:300}}

Page 71: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

Behavioronscale{PropertyAnimation{duration:300}}

}

MouseArea{

anchors.fill:delegate

onClicked:{

categories.currentIndex=index

if(categories.currentUrl==url)

newsModel.reload()

else

categories.currentUrl=url

}

}

}

Thereisroomtoimprovethecategories,includingthebackgroundimagewhichissimplyanImageelement,andcouldformpartofyourexercises.However,itwon'tbecoveredinthischapter.Here,whatwedonextistochangethedisplayingfontsontheWindowsplatform.We'regoingtochangethefonttoTimesNewRomanbyaddingafewlinesinmain.cpp(notmain.qml).

#include<QGuiApplication>

#include<QQmlApplicationEngine>

#include<QFont>

intmain(intargc,char*argv[])

{

QGuiApplicationapp(argc,argv);

#ifdefQ_OS_WIN

app.setFont(QFont(QString("TimesNewRoman")));

#endif

QQmlApplicationEngineengine;

engine.load(QUrl(QStringLiteral("qrc:/main.qml")));

returnapp.exec();

}

Here,weuseapredefinedmacrotolimitthischangefortheWindowsplatforms.BysettingthefontofappwhosetypeisQGuiApplication,allthechildrenwidgets,includingengine,aresubjectedtothischange.Nowruntheapplicationagain;youshouldexpectanewRSSreaderwiththisnewspaper-likefont:

Page 72: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount
Page 73: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

UtilizingScrollViewOurRSSnewsreaderisshapingupnow.Fromnowon,let'sfocusontheunpleasantdetails.Thefirstthingwe'regoingtoaddisascrollbar.Tobemorespecific,ScrollViewisabouttobeadded.

BackintheQt4era,youhadtowriteyourownScrollViewcomponenttogainthissmallyetverynicefeature.AlthoughyoucanutilizeKDEPlasmaComponents'ScrollAreaonX11Platforms,therearenoQtbundledmodulesforthispurpose,whichmeansyoucan'tusetheseonWindowsandMacOSX.ThankstotheopengovernanceoftheQtproject,alotofcommunitycodegetsmerged,especiallyfromtheKDEcommunity.FromQt5.1onwards,wehavetheQtQuick.Controlsmodule,whichhasmanybuilt-indesktopcomponents,includingScrollView.

It'saveryeasytouseelementthatprovidesscrollbarsandcontentframesforitschilditem.TherecanbeonlyonedirectItemchild,andthischildisimplicitlyanchoredtofilltheScrollViewcomponent.ThismeansthatweonlyneedtoanchortheScrollViewcomponent.

Therearetwowaystospecifythechilditem.ThefirstoneistodeclarethechilditeminsidetheScrollViewcomponent'sscope,andtheitemwhichisinsidewillimplicitlybecomethechildoftheScrollViewcomponent.AnotherwayistosetthecontentItemproperty,whichisanexplicitmethod.Inthischapter'sexample,bothwaysaredemonstratedforyou.Thecontentofmain.qmlisshownhere:

importQtQuick2.3

importQtQuick.Window2.2

importQtQuick.XmlListModel2.0

importQtQuick.Controls1.2

importQtQuick.Controls.Styles1.2

import"qrc:/"

Window{

id:mainWindow

visible:true

width:720

height:400

Feeds{

id:categoriesModel

}

ListView{

id:categories

orientation:ListView.Vertical

spacing:3

Page 74: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

model:categoriesModel

delegate:CategoriesDelegate{

id:categoriesDelegate

width:categories.width

}

propertystringcurrentUrl:categoriesModel.get(0).url

}

ScrollView{

id:categoriesView

contentItem:categories

anchors{left:parent.left;top:parent.top;bottom:

parent.bottom;}

width:0.2*parent.width

style:ScrollViewStyle{

transientScrollBars:true

}

}

XmlListModel{

id:newsModel

source:categories.currentUrl

namespaceDeclarations:"declarenamespacemedia=

'http://search.yahoo.com/mrss/';declarenamespaceatom=

'http://www.w3.org/2005/Atom';"

query:"/rss/channel/item"

XmlRole{name:"title";query:"title/string()"}

XmlRole{name:"description";query:"description/string()"

}

XmlRole{name:"link";query:"link/string()"}

XmlRole{name:"pubDate";query:"pubDate/string()"}

//XPathstartsfrom1not0andthesecondthumbnailis

largerandmoreclear

XmlRole{name:"thumbnail";query:

"media:thumbnail[2]/@url/string()"}

}

ScrollView{

id:newsView

anchors{left:categoriesView.right;leftMargin:10;

right:parent.right;top:parent.top;bottom:parent.bottom}

style:ScrollViewStyle{

transientScrollBars:true

}

ListView{

id:newsList

model:newsModel

delegate:NewsDelegate{

width:newsList.width

}

}

}

}

Page 75: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

Sincethechilditemisautomaticallyfilledwithanchors,somelinesinsideListViewaredeleted.MostofthemarejustmovedtoScrollViewthough.YoucanseethatweusetheexplicitwayforcategoriesandtheimplicitwayfornewsList.

LookingintoScrollView,wedefinedacustomstyleelementbyforcingtransientScrollBarstotrue.It'snotedthatthedefaultvalueoftransientScrollBarsisplatformdependent.Thetransientscrollbarsonlyappearwhenthecontentisscrolledandthendisappearwhentheyarenolongerneeded.Anyway,it'sfalsebydefaultonWindows,soweturnitonexplicitly,resultinginabettervisualstyleshownasfollows:

Page 76: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

AddingBusyIndicatorTheabsenceofabusyindicatormakespeopleuncomfortableaswell.Nomatterhowshortorlongindicatoritis,ittakestimetodownloaddataandparseXML.I'mprettysureyou'dliketoaddsuchanindicator,whichtellsuserstocalmdownandwait.Luckily,BusyIndicator,whichissimplyarunningcircle,isanelementofQtQuick.Controls.Thisdoesexactlywhatwewant.

Whatyouneedtodoistoaddtheselinestomain.qmlinsidetheWindowitem:

BusyIndicator{

anchors.centerIn:newsView

running:newsModel.status==XmlListModel.Loading

}

Notethatwedon'tneedtochangethevisiblepropertyofBusyIndicator,becauseBusyIndicatorisonlyvisiblewhentherunningpropertyissettotrue.Inthiscase,wesetrunningtotruewhenthenewsModelstatusisLoading.

Page 77: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

MakingaframelesswindowSimilartowhatwedidinthepreviouschapter,herewedon'twantthebordersofthesystemwindowtodecorateourQtQuickapplication.Thisispartlybecauseitlookslikeawebapplication,whichmakesitseemsoddwithnativewindowdecorations.ThisjobiseveneasierinQMLthaninC++.WecanaddthefollowinglinetoWindowinmain.qml:

flags:Qt.Window|Qt.FramelessWindowHint

AlthoughourRSSreaderrunsinaframelessstyle,thereisnowaytomoveitandit'sdifficulttocloseit,justlikethesituationinthepreviouschapter.SinceourmousehasmanydutiesforthecategoriesandnewsListViewalongwithScrollView,wecan'tsimplyuseanewMouseAreaelementtofilltheWindowroot.Therefore,whatwe'regoingtodoistodrawourowntitlebarand,ofcourse,theexitbutton.

Toaddtheexitbuttonimagetotheqrcfile,right-clickonqml.qrc,selectOpeninEditor,navigatetoAdd|AddFiles,andthenselectclose.png.

TipIt'dbebettertousedifferentresourcefiles(qrc)fordifferenttypesoffiles,whichmakeitmoreorganized.We'lltalkmoreaboutresourcefilesinChapter8,EnablingYourQtApplicationtoSupportOtherLanguages.

Now,addanewQMLTitleBar.qmlfilewhosecontentispastedhere:

importQtQuick2.3

Row{

id:titlebar

width:parent.width

height:22

layoutDirection:Qt.RightToLeft

propertypointmPos:Qt.point(0,0)

Image{

id:closebutton

width:22

height:22

fillMode:Image.PreserveAspectFit

source:"qrc:/close.png"

Page 78: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

MouseArea{

anchors.fill:parent

onClicked:{

Qt.quit()

}

}

}

Rectangle{

width:titlebar.width-closebutton.width

height:titlebar.height

color:"#000"

MouseArea{

anchors.fill:parent

onPressed:{

mPos=Qt.point(mouseX,mouseY)

}

onPositionChanged:{

mainWindow.setX(mainWindow.x+mouseX-mPos.x)

mainWindow.setY(mainWindow.y+mouseY-mPos.y)

}

}

}

}

Here,weuseaQPointobject,mPos,tostorethepositionwhenthemousebuttonisclicked.

NoteAlthoughwemayhavedeclareditasvarorvariantinthepast,formaximumperformanceyoushouldavoidtheuseofvar.Alsonotethatvariantisdeprecatednow,soitshouldn'tbeusedunderanycircumstances.

TheMouseAreaelement,whichisusedformoving,islocatedinsidetheRectangleelement.TherearelotsofpredefinedsignalsandslotsforMouseArea.NotethatweusetheonPressedslotinsteadofonClickedheretogetthemouseposition.Thisisbecausetheclickedsignalisonlyemittedwhenthemousebuttonispressedandthenreleased,whichmakesitunsuitableformovingthewindow.

ThepositionChangedsignalisemittedwhenthemousebuttonispressedandthenmoved.Inadditiontothis,thereisapropertycalledhoverEnabled,whichisfalsebydefault.Ifyousetittotrue,allthemouseeventswillbehandledevenwhennomousebuttonisclicked.Inotherwords,thepositionChangedsignalwillbeemittedwhenthemouseismoving,regardlessofwhetherit'sclickedornot.Therefore,we

Page 79: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

don'tsethoverEnabledtotrueinthisexample.

Nowlet'sgobackandchecktheImageitem.ThefillModeelementdetermineshowanimageshouldbeadjusted.Bydefault,it'llbestretcheddespitetheratio.Here,wesetittopreservetheratiowhilewefittheImage.Thesourcepropertyholdstheimagefilepath.Inthiscase,it'stheclose.pngfilethatisintheResourcesfile,qml.qrc.Herewego;thisisanotherMouseArea,whichsimplymakesImageintoaclosedbutton.

Atlast,it'stimetoaddTitleBartomain.qmlasfollows:

importQtQuick2.3

importQtQuick.Window2.2

importQtQuick.XmlListModel2.0

importQtQuick.Controls1.2

importQtQuick.Controls.Styles1.2

import"qrc:/"

Window{

id:mainWindow

visible:true

width:720

height:400

flags:Qt.Window|Qt.FramelessWindowHint

TitleBar{

id:titleBar

}

Text{

id:windowTitle

anchors{left:titleBar.left;leftMargin:10;

verticalCenter:titleBar.verticalCenter}

text:"BBCNewsReader"

color:"#FFF"

font.pointSize:10

}

Feeds{

id:categoriesModel

}

ListView{

id:categories

orientation:ListView.Vertical

spacing:3

model:categoriesModel

delegate:CategoriesDelegate{

id:categoriesDelegate

width:categories.width

}

Page 80: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

propertystringcurrentUrl:categoriesModel.get(0).url

}

ScrollView{

id:categoriesView

contentItem:categories

anchors{left:parent.left;top:titleBar.bottom;bottom:

parent.bottom;}

width:0.2*parent.width

style:ScrollViewStyle{

transientScrollBars:true

}

}

XmlListModel{

id:newsModel

source:categories.currentUrl

namespaceDeclarations:"declarenamespacemedia=

'http://search.yahoo.com/mrss/';declarenamespaceatom=

'http://www.w3.org/2005/Atom';"

query:"/rss/channel/item"

XmlRole{name:"title";query:"title/string()"}

XmlRole{name:"description";query:

"description/string()"}

XmlRole{name:"link";query:"link/string()"}

XmlRole{name:"pubDate";query:"pubDate/string()"}

//XPathstartsfrom1not0andthesecondthumbnailis

largerandmoreclear

XmlRole{name:"thumbnail";query:

"media:thumbnail[2]/@url/string()"}

}

ScrollView{

id:newsView

anchors{left:categoriesView.right;leftMargin:10;

right:parent.right;top:titleBar.bottom;bottom:

parent.bottom}

style:ScrollViewStyle{

transientScrollBars:true

}

ListView{

id:newsList

model:newsModel

delegate:NewsDelegate{

width:newsList.width

}

}

}

BusyIndicator{

anchors.centerIn:newsView

running:newsModel.status==XmlListModel.Loading

}

Page 81: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

}

WealsouseaTextelement,windowTitle,todisplaythewindowtitleintitleBar.SinceweretrievedatafromBBCNews,it'snotabadideatocallitBBCNewsReaderorjustnameitwhateveryoulike.

Apartfromtheadditionofthetitlebar,somecodeneedstobemodifiedtospareroomforit.BoththeScrollViewcomponent'sanchoredtopshouldbechangedtotitleBar.bottominsteadofparent.top,otherwisethetitlebarwillbeplacedpartiallyontopofthesetwoscrollviews.

Givetheapplicationarun;itshoulddeliveranewvisualstyle.Althoughitlooksmorelikeawebapplication,thewholeinterfaceiscleanandintegrated.AnotherbenefitofthischangeisaunifiedUIacrossallplatforms.

Page 82: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

DebuggingQMLThemostcommonpracticetodebugQMListheuseoftheAPIconsole.JavaScriptdevelopersshouldbefamiliarwiththisbecauseoftheconsolesupportinQML.TherelationshipsbetweentheconsolefunctionsandtheQt/C++QDebugfunctionsaregivenasfollows:

QML Qt/C++

console.log() qDebug()

console.debug() qDebug()

console.info() qDebug()

console.warn() qWarning()

console.error() qCritical()

Withtheprecedingsupportspresent,QMLisjustlikeJavaScriptprogramming.Atthesametime,thefollowingfunctionsarealsointroducedinQML:

Functions Description

console.assert()

Thisfunctiontestswhethertheexpressionistrue.Ifnot,itwillwriteanoptionalmessagetotheconsoleandprintthestacktrace.

console.exception()ThisfunctionprintsanerrormessagetogetherwiththestacktraceoftheJavaScriptexecutionatthepointitiscalled.

Page 83: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

console.trace()ThisfunctionprintsthestacktraceoftheJavaScriptexecutionatthepointitiscalled.

console.count()Thisfunctionprintsthecurrentnumberoftimesaparticularpieceofcodehasbeenexecuted,alongwithamessage.

console.time()

console.timeEnd()

Thispairoffunctionswillprintthetimethataparticularpieceofcodebetweenthemtakesinmilliseconds.

console.profile()

console.profileEnd()

ThispairoffunctionsprofilesboththestateofQDeclarativeEngineaswellastheV8callmethods.However,youneedtoattachtheQMLProfilertooltotheapplicationbeforeconsole.profileEnd()iscalled.

Inadditiontotheprecedingusefulfunctions,thecommonDebugmodeinQtCreatorisavailableforQMLaswell.TheoperationsarealmostidenticaltoC++debugging.Youcansetthebreakpoints,observevalues,andsoon.However,thereisonemorethingprovidedforQML.It'stheQML/JSConsole!QtCreatordoesn'tshowtheQML/JSConsolebydefault,youhavetoturnitonmanually.Justclickonthesmallbutton(theredcircleinthefollowingscreenshot),andthentickQML/JSConsole:

Tip

Page 84: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

Whentheapplicationisinterruptedbyabreakpoint,youcanusetheQML/JSConsoletoexecutetheJavaScriptexpressionsinthecurrentcontext.Youcanchangethepropertyvaluestemporarily,withouteditingthesource,andviewtheresultsintherunningapplication.

TheQML/JSConsoletabshowsthedebugoutput,boththeQtdebugmessagesandJavaScriptconsolemessages,inanappealingway.Itprovidesabuttongrouptohelpyoufilterinformation,warnings,anderrors.Therefore,justusethisQML/JSConsoletabtoreplaceApplicationOutputwhenyoudebugQtQuickapplications.

Page 85: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

SummaryInthischapter,wewentthroughathoroughintroductiontoQtQuick.Wealsocoveredmodel-viewprogramming,whichisavitalconceptinbothQt/C++andQtQuick/QML.YoumayalsofindthatQMLisinsomewayanextensibleversionofJavaScript.ThisisanadditionalbonusforJavaScriptdevelopers.However,it'snotdifficulttostartifyou'veneverwrittenascriptbefore.Onceyoustart,you'llgettoexplorethefascinatingqualitiesofQtQuick.We'regoingtoshowyouhowtoaccesscameradevicesusingQtinthenextchapter.

Page 86: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

Chapter4.ControllingCameraandTakingPhotosThroughthischapter,you'llfindhoweasyitistoaccessandcontrolacamerawithQt.Theexampleinthischapteralsodemonstrateshowtoutilizethestatusbarandmenubar.InadditiontothetraditionalQtWidgetapplications,thereisaQMLcameraexample,whichdoesthesamethingasQt/C++butinamoreelegantway.Thefollowingtopics,whicharecoveredinthischapter,willextendyourapplication:

AccessingthecamerainQtControllingthecameraDisplayingerrorsinthestatusbarDisplayingthepermanentwidgetsinthestatusbarUtilizingthemenubarUsingQFileDialogUsingtheQMLCamera

AccessingthecamerainQtAlthoughwewon'ttalkaboutthetechnicaldetailsofhowacameraworks,theoverviewoftheimplementationofacamerainQtwillbecovered.SupportforacameraisincludedinQtMultimedia,whichisamodulethatprovidesarichsetofQMLtypesandC++classestohandlemultimediacontent.Thingssuchasaudioplayback,camera,andradiofunctionalityareshown.Tocomplementthis,theQtMultimediaWidgetsmoduleprovideswidget-basedmultimediaclassestomaketheworkeasier.

Therearesomeclassestohelpusdealwiththecamera.Forinstance,viewfinderletsauserlookthroughthecameratocompose,andinmanycasesfocus,thepicture.InQt/C++,youcanuseQGraphicsViewalongwithQGraphicsVideoItemtodothisjob.QGraphicsViewprovidesawidgettodisplaythecontentsofQGraphicsScene.Inthiscase,QGraphicsVideoItemisanitemofthescene.Thisview-scene-itemistheGraphicsViewFramework.Fordetailsonthisconcept,visithttp://doc.qt.io/qt-5/graphicsview.html.Inthisexample,weuseQCameraViewfinder,whichisthededicatedviewfinderclassandissimplerandmorestraightforward.

Tocaptureaphoto,weneedtousetheQCameraImageCaptureclass,whichrecordsthemediacontent,whilethefocusandzoomaremanagedbytheQCameraFocusclass.

Page 87: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

Afterall,QCameraplaysacoreroleinthisprocess.TheQCameraclassprovidesaninterfacetoaccessthecameradevices,includingwebcamsandmobiledevicecameras.Thereisanotherclass,QCameraInfo,whichcanlistalltheavailablecameradevicesandchoosewhichonetouse.Thefollowingdiagramwillhelpyouunderstandthis:

Toseeademonstration,createanewQtWidgetApplicationprojectnamedCameraDemo.EdittheCameraDemo.profile.AddmultimediamultimediawidgetstoQTbyappendingaline,asshownhere,oraddtwomodulestothepredefinedQTline:

QT+=multimediamultimediawidgets

Afterthismodification,youneedsavethefileandnavigatetoBuild|Runqmaketoloadthesenewmodules.Let'seditthemainwindow.uifileofCameraDemotoaddsomewidgetstousethecamerabyperformingthefollowingsteps:

1. Removethestatusandmenubars.Theywillbere-addedinthenextsections.Fornow,they'reremovedforacleaneruserinterface.

2. DragWidgetintotheframe.3. Changeitsnametoviewfinder.

Page 88: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

4. Right-clickonviewfinderandselectPromoteto….5. FillinQCameraViewfinderinthePromotedclassnamefield.Remembertotick

theGlobalincludecheckboxbecausethisisapredefinedQtclass.ClickonAdd,andthenonPromote.

6. SetMainWindowtoLayOutHorizontally.7. DragaVerticallayoutontheright-handsideofviewfinder.Followingthis,

componentswillbeaddedtothelayout.8. AddLabel,whichisusedtodisplaythecapturedimage.Notethat,herewedon't

useQGraphicsView,simplybecauseQLabelisgoodenoughforthispurposeandismucheasier.

9. RenameitaspreviewLabelandclearitstext.10. DragComboBoxjustbeneathpreviewLabel.11. RenameitascameraComboBoxsinceit'llbeusedtodisplayalltheavailable

cameradevices.12. AddaPushButtonnamedcaptureButtonbelowComboBoxintheVerticallayout

tolettheuserclicktotakeaphoto.ThisbuttonshouldhavethetextCaptureonit.

Itshouldlooklikethefollowingscreenshot:

Now,gobacktothemainwindow.hedit,asshownhere:

#ifndefMAINWINDOW_H

#defineMAINWINDOW_H

Page 89: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

#include<QMainWindow>

#include<QCamera>

#include<QCameraInfo>

#include<QCameraImageCapture>

namespaceUi{

classMainWindow;

}

classMainWindow:publicQMainWindow

{

Q_OBJECT

public:

explicitMainWindow(QWidget*parent=0);

~MainWindow();

private:

Ui::MainWindow*ui;

QList<QCameraInfo>camList;

QCamera*camera;

QCameraImageCapture*imgCapture;

privateslots:

voidonCameraChanged(int);

voidonCaptureButtonClicked();

voidonImageCaptured(int,constQImage&);

};

#endif//MAINWINDOW_H

Asusual,inordertousetheclassesintheprecedingcode,wehavetoincludethemproperly.Inadditiontothis,weusecamList,whichisatypeofQList<QCameraInfo>,tostoretheavailablecameradevices.SinceQListisatemplateclass,wehavetopassthetypeoflistelement,whichisQCameraInfointhiscase,totheconstructor.

Theseprivateslotsareresponsibleforthecameracontrols,namely,changingthecameradeviceandclickingthecapturebutton.Meanwhile,onImageCapturedisusedtohandletheimageCapturedsignalofQCameraImageCapture.

Thecontentofthemaindow.cppfileisshownasfollows:

#include"mainwindow.h"

#include"ui_mainwindow.h"

MainWindow::MainWindow(QWidget*parent):

QMainWindow(parent),

ui(newUi::MainWindow)

{

ui->setupUi(this);

camera=NULL;

Page 90: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

connect(ui->captureButton,&QPushButton::clicked,this,

&MainWindow::onCaptureButtonClicked);

connect(ui->cameraComboBox,static_cast<void(QComboBox::*)

(int)>(&QComboBox::currentIndexChanged),this,

&MainWindow::onCameraChanged);

camList=QCameraInfo::availableCameras();

for(QList<QCameraInfo>::iteratorit=camList.begin();it

!=camList.end();++it){

ui->cameraComboBox->addItem(it->description());

}

}

MainWindow::~MainWindow()

{

deleteui;

}

voidMainWindow::onCameraChanged(intidx)

{

if(camera!=NULL){

camera->stop();

}

camera=newQCamera(camList.at(idx),this);

camera->setViewfinder(ui->viewfinder);

camera->setCaptureMode(QCamera::CaptureStillImage);

camera->start();

}

voidMainWindow::onCaptureButtonClicked()

{

imgCapture=newQCameraImageCapture(camera,this);

connect(imgCapture,&QCameraImageCapture::imageCaptured,

this,&MainWindow::onImageCaptured);

camera->searchAndLock();

imgCapture-

>setCaptureDestination(QCameraImageCapture::CaptureToFile);

imgCapture->capture();

}

voidMainWindow::onImageCaptured(int,constQImage&img)

{

QPixmappix=QPixmap::fromImage(img).scaled(ui-

>previewLabel->size(),Qt::KeepAspectRatio);

ui->previewLabel->setPixmap(pix);

camera->unlock();

imgCapture->deleteLater();

}

Let'shavealookattheconstructorfirst.WegivecameraaNULLaddresstomarkthatthereisnocameraallocatedand/oractive.Thisisexplainedlater.

SincethereareoverloadedsignalfunctionsforQComboBox::currentIndexChanged,

Page 91: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

youhavetospecifythesignalthatyouwantwithstatic_cast.Otherwise,thecompilerwouldcomplainandfailtocompile.Onlythenewsyntaxstatementofthesignalandslotareaffected,whichmeanstheoldsyntaxstatement,shownhere,won'tposeanyerrors:

connect(ui->cameraComboBox,SIGNAL(currentIndexChanged(int)),

this,SLOT(onCameraChanged(int)));

However,asmentionedpreviously,thenewsyntaxhasmanyadvantagesandit'shighlyrecommendedthatyoureplacetheoldone.

Aswecontinue,wecanfillincamListwiththeavailablecamerassinceavailableCamerasisastaticmemberfunctionofQCameraInfo,whichreturnsalistofallavailablecamerasonthesystem.Also,youcanpassanargumenttospecifythecameraposition,suchasthefrontorbackcamera,whichisprettyusefulonmobileplatforms.

Then,weaddalltheitemsincamListtoourcameracombobox.Here,it'stheiteratorthatwalksthroughthelistandoperateseachone.Usingiteratorsisveryfastwhendealingwithalist,array,andsoon.Qtsupportsthismethod,includingbothJava-styleandSTL-styleiterators.Inthiscase,wepreferanduseSTL-styleiterators.ThedescriptionfunctionofQCameraInforeturnsahuman-readabledescriptionofthecamera.

Now,let'sgoinsideonCameraChanged.Beforetheconstructionofthecamera,weneedtocheckwhetherthereisacamerapresentalready.Ifthereis,westoptheoldcamera.Then,wesetuptheviewfinderclassusingtheviewfinderwidget,whichwedidintheDesignmode.AfterspecifyingthecapturemodetoCaptureStillImage,wecanstartthecamera.

TipThecameracannotstartagainifit'snotdeallocated(stopped).

Consequently,itgoestotheonCaptureButtonClickedslot.Similarly,theimgCaptureobjectisconstructedbypassingthecameraandthisargumentsasitsQCameratargetandQObjectparentrespectively.Then,wehavetoconnecttheimageCapturedsignaltotheonImageCapturedslotofMainWindow.Now,letcamera->searchAndLock()lockallthecamerasettings.Thisfunctionisinresponsetotheshutterbuttonbeinghalfpressed.Beforetakingashot,wesetthecapturedestinationtothefile.AlthoughitcanbesettoabufferusingtheQCameraImageCapture::CaptureToBufferflagifneeded,bearinmindthatit'snotsupportedonallplatforms.

Page 92: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

Ifeverythinggoeswell,animagewillbecapturedbycameraandtheimageCapturedsignalwillbeemitted.Then,theonImageCapturedslotfunctionwillbeexecuted.Insidethisfunction,wescalethecapturedimagetothesizeofourpreviewLabel.Then,justsetQPixmapforpreviewLabelandunlockcamera.Intheend,wecallthedeleteLater()functiontosafelydeletetheimgCaptureinstance.

NoteYoushouldexplicitlyindicateQt::KeepAspectRatio,otherwiseitusesthedefaultQt::IgnoreAspectRatioflag.

Now,runthedemoandseewhatyouget.

Justaswedidinthepreviouschapters,feelfreetochangethewindow'stitle,applicationfont,andsoon.Thesetrivialtweakswon'tbedetailedanymore.

Page 93: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

ControllingthecameraTheQCameraFocusclassismentionedtocontrolthezoomandfocusofthecamera.Speakingofzoom,Qtsupportsbothopticalanddigitalzoom.Asweallknow,opticalzoomoffersabetterqualitythandigital.Hence,opticalzoomshouldtakepriorityoverdigital.

DragahorizontalsliderandalabeltoMainWindowpane'sverticalLayoutjustabovethecapturebutton.NamethemzoomSliderandzoomLabel,respectively.RemembertochangethetextofzoomLabeltoZoomandHorizontalinalignmenttoAlignHCenter.SinceQtdoesn'tprovideafloatingpointnumberslider,wesimplymultiply10togetanintegerintheslider.Hence,changetheminimumvalueofzoomSliderto10,whichmeanszoomby1.0.

IncludeQCameraFocusinmainwindow.handaddthesetwoprivatemembers:

QCameraFocus*cameraFocus;

qrealmaximumOptZoom;

TipNoteverycamerasupportszoom.Ifitdoesn't,themaximumzoomis1.0,whichappliestobothopticalanddigitalzoom.

Thereisatypenamedqreal,whichisbasicallyadoublevalue.ItwasfloatontheARMplatformsforperformanceconcernsanddoubleonothers.However,QthasuseddoubleonARMbydefaultsincetheQt5.2version.Anyway,usingqrealisrecommendediftheapplicationisdeployedondifferenthardwareplatforms.

Anewslotalsoneedstobedeclared:

voidonZoomChanged(int);

Now,connectzoomSliderintheMainWindowclass'constructor:

connect(ui->zoomSlider,&QSlider::valueChanged,this,

&MainWindow::onZoomChanged);

However,QCameraFocuscan'tbeconstructedexplicitly.Instead,itcanonlyberetrievedfromtheQCameraclass.So,wegetcameraFocusjustaftertheconstructionofthecameraargumentinsideonCameraChanged:

Page 94: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

cameraFocus=camera->focus();

Then,setupmaximumOptZoomandthemaximumvalueofzoomSlider:

maximumOptZoom=cameraFocus->maximumOpticalZoom();

ui->zoomSlider->setMaximum(maximumOptZoom*cameraFocus-

>maximumDigitalZoom()*10);

Ifthecameradoesn'tsupportzoomatall,thesliderwon'tbeabletoslide.ThedefinitionoftheonZoomChangedslotisshowninthefollowinglines:

voidMainWindow::onZoomChanged(intz)

{

qrealzoom=qreal(z)/10.0;

if(zoom>maximumOptZoom){

cameraFocus->zoomTo(maximumOptZoom,zoom/

maximumOptZoom);

}

else{

cameraFocus->zoomTo(zoom,1.0);

}

}

Asyoucansee,thefirstparameterofzoomToistheopticalzoomfactorwhiletheotheristhedigitalzoomfactor.

Page 95: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

DisplayingerrorsonthestatusbarFirstofall,therecouldbeerrorsduringthewholecameraprocessandit'sagoodpracticetomaketheuserawareofwhattheerroris.Itcanbedonebyapop-updialogand/orstatusbar.Youdon'twanttoalerttheusertoeverytrivialerror.Therefore,it'dbebettertouseapop-updialogonlyforcriticalerrors,whiledisplayingnon-criticalerrorsandwarningsonthestatusbar.

Qtbegansupportingthestatusbaralongtimeago.TheQStatusBarclassistheonethatprovidesahorizontalbarsuitableforpresentingstatusinformation.Thestatusofthecameracanbedisplayedaswellandit'llbeintroducedinlatertopics.

Tousethestatusbar,editmainwindow.ui,right-clickonMainWindow,andselectCreateStatusBarifitdoesn'texistorwaspreviouslyremoved.

Then,weshoulddeclaretwoslotstohandlethecameraandimagecaptureerrors,respectively.Addthesetwolinestoprivateslotsinmainwindow.h:

voidonCameraError();

voidonImageCaptureError(int,QCameraImageCapture::Error,

constQString&);

Thedefinitionsinmainwindow.cppareshownasfollows:

voidMainWindow::onCameraError()

{

ui->statusBar->showMessage(camera->errorString(),5000);

}

voidMainWindow::onImageCaptureError(int,

QCameraImageCapture::Error,constQString&err)

{

ui->statusBar->showMessage(err,5000);

imgCapture->deleteLater();

}

ThissimplymakesstatusBarshowatemporarymessageforfiveseconds.EvenifyoupasszerotoshowMessage,it'sstillatemporarymessage.Inlatercases,itwon'tdisappearafteragivenperiod;instead,it'lldisappearifthereisanewtemporarymessage.

SincethesignalerrorisdifferentinQCamerafromQCameraImageCapture,weusedifferentslotstohandleit.ForQCamera,theerrorsignalfunctionhasQCamera::Errorastheonlyargument.

Page 96: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

Bycontrast,QCameraImageCapture::errorprovidesthreearguments:int,QCameraImageCapture::Error,andaconstQStringreference.Therefore,wecanmakeuseofthissignalbyusingitserrorstringdirectly.

Don'tforgettoconnectthesignalsandslots.Here,insidetheonCameraChangedfunction,justafterthecameraconstruction,connectthecameraerrorandtheonCameraErrorslot.

connect(camera,static_cast<void(QCamera::*)

(QCamera::Error)>(&QCamera::error),this,

&MainWindow::onCameraError);

AsthereisanotheroverloadedfunctioncallederrorintheQCameraclass,wehavetousestatic_casttospecifythesignalfunction,aswedidinQComboBox.

Similarly,addtheconnectstatementaftertheimgCaptureobject'sconstructionintheonCaptureButtonClickedfunction.

connect(imgCapture,static_cast<void(QCameraImageCapture::*)

(int,QCameraImageCapture::Error,constQString&)>

(&QCameraImageCapture::error),this,

&MainWindow::onImageCaptureError);

Itisanotheroverloadederrorsignalfunction.However,it'stediousbecauseofthreearguments.

Page 97: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

PermanentwidgetsinthestatusbarSometimes,wewantasortofindicatorinsidethestatusbartodisplayreal-timestatus,suchasthecamerastatus.Thisisinappropriateifit'scoveredbytemporarymessages.Insuchacase,QStatusBarprovidestheinsertPermanentWidgetfunctiontoaddawidgettothestatusbarpermanently.Itmeansthatitwon'tbeobscuredbytemporarymessagesandislocatedonthefarrightofthestatusbar.

Firstly,let'smakeacamerastatuswidget.AddanewC++classnamedCameraStatusWidgetthatinheritsfromQWidget,butuseQLabelasthebaseclass.WeuseQLabelasthebaseclassbecausethestatusofthecameraisdisplayedintextandisbasicallyacustomizedlabelwidget.Thecamerastatuswidget.hcontentisshownasfollows:

#ifndefCAMERASTATUSWIDGET_H

#defineCAMERASTATUSWIDGET_H

#include<QLabel>

#include<QCamera>

classCameraStatusWidget:publicQLabel

{

Q_OBJECT

public:

explicitCameraStatusWidget(QWidget*parent=0);

publicslots:

voidonCameraStatusChanged(QCamera::Status);

};

#endif//CAMERASTATUSWIDGET_H

Besidesthe#include<QCamera>,weonlyaddadeclarationoftheonCameraStatusChangedslottothisheaderfile.Therelevantcamerastatuswidget.cppsourcefileispastedasfollows:

#include"camerastatuswidget.h"

CameraStatusWidget::CameraStatusWidget(QWidget*parent):

QLabel(parent)

{

}

voidCameraStatusWidget::onCameraStatusChanged(QCamera::Status

s)

{

QStringstatus;

switch(s){

Page 98: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

caseQCamera::ActiveStatus:

status=QString("Active");

break;

caseQCamera::StartingStatus:

status=QString("Starting");

break;

caseQCamera::StoppingStatus:

status=QString("Stopping");

break;

caseQCamera::StandbyStatus:

status=QString("Standby");

break;

caseQCamera::LoadedStatus:

status=QString("Loaded");

break;

caseQCamera::LoadingStatus:

status=QString("Loading");

break;

caseQCamera::UnloadingStatus:

status=QString("Unloading");

break;

caseQCamera::UnloadedStatus:

status=QString("Unloaded");

break;

caseQCamera::UnavailableStatus:

status=QString("Unavailable");

break;

default:

status=QString("Unknown");

}

this->setText(status);

}

TipAlwayshandleexceptionsintheswitchstatements.

QCamera::Statusisanenumtype.That'swhywehavetouseaswitchstatementtotranslatethestatustostring.Sincewehaveourcamerastatuswidgetnow,it'stimetoaddittothestatusbar.Editmainwindow.handaddaCameraStatusWidgetpointerasfollows:

CameraStatusWidget*camStatusWid;

Don'tforgettoincludethecamerastatuswidget.hheaderfile.Then,setupcamStatusWidjustafterui->setupUi(this)byaddingthefollowinglines:

camStatusWid=newCameraStatusWidget(ui->statusBar);

Page 99: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

ui->statusBar->addPermanentWidget(camStatusWid);

NavigatetotheonCameraChangedfunction;weneedtoconnecttheQCamera::statusChangedsignal.Justaddthefollowinglineafterconstructionofthecamera:

connect(camera,&QCamera::statusChanged,camStatusWid,

&CameraStatusWidget::onCameraStatusChanged);

Likewise,wecanaddcurrentzoomtothestatusbar.Infact,forthissmallandeasy-to-dowidget,wedon'tneedtocreateanewclass.Instead,we'llusetheexistingQLabelclasstoachievethisbydeclaringanewmember.Inmainwindow.h,addanewprivatemember:

QLabel*zoomStatus;

Meanwhile,constructandinsertthezoomStatusintostatusBarintheMainWindowclassconstructorinmainwindow.cpp:

zoomStatus=newQLabel(QString::number(qreal(ui->zoomSlider-

>value())/10.0),this);

ui->statusBar->addPermanentWidget(zoomStatus);

Here,weuseanumberfunction,whichisastaticpublicfunctionoftheQStringclasstoconvertanumber(itcanbedoubleorinteger)toQString.InordertoupdatezoomStatusintime,appendthislinetotheonZoomChangedfunction:

zoomStatus->setText(QString::number(zoom));

Afterthesemodifications,theapplicationwillrunasshowninthefollowingscreenshot:

Page 100: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount
Page 101: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

UtilizingthemenubarNowthatyouhavefinishedthebaratthebottom,it'stimetobegintheoneontop—themenubar.Similartothestatusbar,right-clickonMainWindowintheDesignmode,andselectCreateMenuBarifitdoesn'texistorwaspreviouslyremoved.

Then,justfollowthehints.AddaFilemenucontainingtheExitaction.AnothermenucouldbeAbout,whichcontainstheAboutCameraDemoaction.YoushouldknowthattheseactionsareabletochangeintheActionEditorpanel,whichisinthesameplaceasSignals&SlotsEditor.

Asshowninthefollowingscreenshot,thenamesoftheseactionsarechangedtoactionAboutandactionExit,respectively.Inadditiontothis,thereisashortcut,Ctrl+Q,foractionExit.Justdouble-clickontheactionandaddshortcutsbypressingtheshortcutyouwant.Thisisshowninthefollowingscreenshot:

Page 102: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

WealreadyusedQMenuandQActioninChapter2,BuildingaBeautifulCross-platformClock.ThedifferencehereisthatyouuseQMenuasthemenubar,andsetitupitinDesignmodeinsteadofwritingcode.ButwhyisitcalledQAction?Thisisbecausetheusercantriggeracommandonthemenu,toolbar,orkeyboardshortcut.Theyexpectthesamebehaviorregardlessofwhereitis.Therefore,itshouldbeabstractedintoanaction,whichcanbeinsertedintothemenuortoolbar.YoucansetittothecheckableQActionoptionanduseitasasimpleQCheckboxoption.

Let'sfinishactionExitfirst,sinceit'ssimplerthantheotherone.ForactionExit,weonlyneedoneconnectstatementtomakeitwork.AddthefollowingstatementtotheMainWindowclassconstructorinthemainwindow.cppfile:

connect(ui->actionExit,&QAction::triggered,this,

&MainWindow::close);

Thetriggeredsignalwillbeemittedbyeitheramouseclickorakeyboardshortcut(ifthereisashortcut).SinceweconnectittothecloseslotofMainWindow,it'llcloseMainWindow,whichresultsinexitingtheentireapplication.

Meanwhile,weneedtodeclareaslottofulfilltheconnectionwithactionAbout.Asusual,declareitinthemainwindow.hheaderfile.

voidonAboutTriggered();

Youmaythinkthatwe'regoingtocreateanewclassjusttoshowanAboutdialog.Well,wedon'thavetocooktheAboutdialogourselvesbecauseQthasalreadydonethisforus.It'sincludedinQMessageBox,soyoushouldincludeitwiththefollowingline:

#include<QMessageBox>

Thisisthedefinitionoftheslot:

voidMainWindow::onAboutTriggered()

{

QMessageBox::about(this,QString("About"),QString("Camera

DemonstrationofQt5"));

}

NoteTheQMessageBoxclassprovidesamodaldialogforinformingoraskingtheuseraquestionandreceivingananswer.

Page 103: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

Almosteverykindofpop-updialogcanbefoundinQMessageBox.Here,weusethestaticAboutfunctiontocreateanAboutdialog.Ithasthreearguments.ThefirstoneistheparentQObjectpointer,followedbythetitleandcontext.RemembertoconnectthesignalandslotintheMainWindowclassconstructor.

connect(ui->actionAbout,&QAction::triggered,this,

&MainWindow::onAboutTriggered);

Ifyoucompileandruntheapplicationagain,trytotriggertheAboutdialog,whichwouldlooksimilartothefollowingscreenshot:

NoteInadditiontoAbout,thereareotherusefulstaticpublicmembersofQMessageBox.Mostcommonly,critical,information,question,and,warningareusedtopopupamessagebox.Sometimes,you'llseeanAboutQtentryinthemenubar,whichistocalltheaboutQtfunction.

Infact,theAboutdialogwilldisplayaniconifitexists.Thereisanemptyspacesinceitlacksanicon.Theorderofthesearchiconsisshownasfollows:

Thisfirsticonwillbeparent->icon(),ifitexists.Thesecondiconwillbethetop-levelwidget,whichcontainsparent.Thethirdiconwillbetheactivewindow.ThefourthiconwillbetheInformationicon.

Page 104: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

UsingQFileDialogThelaststepoftakingaphotoistosaveittodisk.Atthispoint,theprogramsavesanimagetothefile,butthelocationisdeterminedbythecamerabackend.Wecansimplyuseadialog,lettingtheuserchoosethedirectoryandthefilenameofthephoto.ThereisaQFileDialogclasstohelpmaketheworkeasier.TheeasiestwaytocreateaQFileDialogclassistousethestaticfunctions.Therefore,edittheonCaptureButtonClickedfunctioninthemainwindow.cppfile.

voidMainWindow::onCaptureButtonClicked()

{

imgCapture=newQCameraImageCapture(camera,this);

connect(imgCapture,static_cast<void

(QCameraImageCapture::*)(int,QCameraImageCapture::Error,

constQString&)>(&QCameraImageCapture::error),this,

&MainWindow::onImageCaptureError);

connect(imgCapture,&QCameraImageCapture::imageCaptured,

this,&MainWindow::onImageCaptured);

camera->searchAndLock();

imgCapture-

>setCaptureDestination(QCameraImageCapture::CaptureToFile);

QStringlocation=QFileDialog::getSaveFileName(this,

QString("SavePhotoAs"),QString(),"JPEGImage(*.jpg)");

imgCapture->capture(location);

}

Here,we'reusingthegetSaveFileNamestaticfunctiontocreateafiledialogtoreturnthefilethattheuserselected.IftheuserclicksonCancel,thelocationtypewouldbeanemptyQStringreferenceandtheimagewillbestoredinadefaultlocation.Thefiledoesn'tneedtoexist.Infact,ifitexists,therewillbeanoverwritedialog.Thisfunction'sprototypeispastedasfollows:

QStringQFileDialog::getSaveFileName(QWidget*parent=0,

constQString&caption=QString(),constQString&dir=

QString(),constQString&filter=QString(),QString*

selectedFilter=0,Optionsoptions=0)

ThefirstargumentistheQObjectparent,asusual.Thesecondoneisthedialog'stitle,followedbythedefaultdirectory.Thefilterobjectisusedtorestrictthefiletypeandit'spossibletousemultiplefiltersthatareseparatedbytwosemicolons,;;.Hereisanexample:

"JPEG(*.jpeg*.jpg);;PNG(*.png);;BMP(*.bmp)"

Page 105: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

SettingselectedFiltercanchangethedefaultfilter.Lastly,Optionsisusedtodefinethebehaviorsofthefiledialog.Formoredetails,refertotheQFileDialogdocumentation.

Page 106: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

QMLcameraSofar,wetalkedabouthowtoaccessandcontrolthecamerainQt/C++.Nowit'stimetoseehowQMLdoesinthisarea.Althoughtherearesomelimitations,you'llfindit'smucheasierandmoreeleganttodothisinQtQuick/QMLbecauseofthemanypackagesthatQthastooffer.

CreateanewQtQuickapplicationproject.Themain.qmlcontentisshownasfollows:

importQtQuick2.3

importQtQuick.Controls1.2

importQtMultimedia5.3

import"qrc:/"

ApplicationWindow{

visible:true

width:640

height:480

title:qsTr("QMLCameraDemo")

Camera{

id:camera

imageCapture{

onImageCaptured:{

photoPreview.source=preview

photoPreview.visible=true;

previewTimer.running=true;

}

}

}

VideoOutput{

id:viewfinder

source:camera

anchors.fill:parent

}

Image{

id:photoPreview

anchors.fill:viewfinder

}

Timer{

id:previewTimer

interval:2000

onTriggered:photoPreview.visible=false;

}

CaptureButton{

Page 107: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

anchors.right:parent.right

anchors.verticalCenter:parent.verticalCenter

diameter:50

}

}

Letmewalkyouthroughthisone.

CameraandVideoOutputareprovidedbytheQtMultimediamodule.SimilartotheQt/C++classes,theCameratypeisidenticaltotheQCameraclass.ThepreviewisdealtwithdifferentlywhenVideoOutputisusedasviewfinder.Animageobjectisusedtodisplaythecapturedphotoandit'sonlyvisiblefor2secondseachtimeapictureistaken.ThisphotoPreviewiscontrolledbythetimer,previewTimer.Inotherwords,the2secondsshowupofphotoPreviewdependsonthispreviewTimertimer.Atthesametime,thecameratype'simageCapturewillprovidethepreviewimagetophotoPreviewandturnonpreviewTimeronceitcapturesaphoto.

ThelastpieceisCaptureButton,whichisnotprovidedbyQtbutwritteninanotherfile,CaptureButton.qml.Itscontentisshowninthefollowingcode:

importQtQuick2.3

Rectangle{

propertyrealdiameter

width:diameter

height:diameter

color:"blue"

border.color:"grey"

border.width:diameter/5

radius:diameter*0.5

MouseArea{

anchors.fill:parent

onClicked:camera.imageCapture.capture()

}

}

SincethereisnocircularshapeprovidedbyQtQuick,weusethisRectangleobjectasaworkaroundtodisplayitasacircle.Justlikewhatwedidinthepreviouschapter,defineadiameterpropertytoholdbothheightandwidth.Thetrickistheradiusvalue.Bysettingittohalfthediameter,thisRectangleobjectbecomescircular.Lastbutnotleast,addMouseAreatorespondtoauser'sclick.It'sapitythatMouseAreacan'tbecircular,sojustleaveitandfillinthebutton.

Nowyoucanrunyourapplication,anditshouldbesomethingsimilartothis:

Page 108: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

It'snotaspowerfulastheQt/C++demo.Thefirstthingyouprobablynoticeisthatyoucan'tchangethecameradevice.It'smissinginthecurrentversionofQt,butitshouldbesupportedinthefuture.Inthemeantime,theonlysolutiontothisistowriteaC++pluginwhilethemainpartisstillwritteninQML.SincedevelopingaC++pluginforQMLwillbecoveredinalaterchapter,we'llsimplyskipthisparthere.

WecanmakethefiledialoginQMLinanevenmoreelegantway.QtQuickprovidescommonly-useddialogsthroughtheQtQuick.Dialogsmodule.Therefore,firstimportthismodule:

importQtQuick.Dialogs1.2

What'reweinterestedinistheFileDialogtype,whichprovidesabasicfilechooser.Itallowstheusertoselectexistingfilesand/ordirectories,orcreatenewfilenames.Itusesthenativeplatformfiledialogswhereverpossible.Tousethistype,addFileDialoginsideApplicationWindowinthemain.qmlfile.

FileDialog{

id:saveDlg

propertystringlocation

Page 109: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

title:"SavePhotoAs"

selectExisting:false

nameFilters:["JPEG(*.jpg)"]

onAccepted:{

location=saveDlg.fileUrl

camera.imageCapture.captureToLocation(location.slice(8))

}

}

ThestringtypeinQMLisanextendedversionoftheJavaScriptstringtype.Whereverpossible,youshouldavoidthevarkeywordandusetheexacttype,suchasint,double,andstring.AccordingtotheQMLdocumentation,thiswillimproveperformancesincethemachinedoesn'tneedtoguessthedatatype.Here,wedeclarelocation,whichisastringtype,whiletherestofitspropertiesaresimilartothedialogsettingsinQt/C++,itstitle(caption),andnameFilters.YoushouldsettheselectExistingpropertytofalse,asitistruebydefault.Otherwise,it'llbehavelikeanopenfiledialog.

InsidetheonAcceptedhandler,passthefileUrlvaluetolocationfirst.Thishandleristheresponsetotheacceptedsignal,whichisemittediftheuserselectsafilesuccessfully.ThefileUrlpropertywillthenbechanged.It'sinaURIformat,whichhasanextrafile:///prefix.Inadditiontothis,thereiscurrentlyanissueifweexecutesliceonfileUrldirectly.Soasaworkaround,weusetheexplicitlydeclaredstringlocationtoinvoketheslicefunction.ThisisaJavaScriptfunction,whichwillreturnanewstringtypethatcontainstheextractedpartsofastring.Theslicemethod'sprototypeisslice(start,end)whereendwillbetheendofthestringtypeifit'somitted.Also,notethatthecharacteratthestartpositionisincludedandtheindexstartsfromzero.Afterthat,wesimplycallthecaptureToLocationfunctionofimageCapturetostoretheimageattheselectedlocation.

Inordertomakeitwork,wehavetochangethebehaviorofCaptureButton.EdittheCaptureButton.qmlfileandchangeMouseArea,asshowninthefollowinglines:

MouseArea{

anchors.fill:parent

onClicked:saveDlg.open()

onPressed:parent.color="black"

onReleased:parent.color="blue"

}

Inadditiontothis,tochangetheonClickedhandler,wealsoaddonPressedandonReleasedtoletithavethepusheffect.Asyoucansee,theopen()functionwillexecuteourFileDialog.Onadesktopoperatingsystem,suchasWindows,theplatformfiledialogisusedasshownhere:

Page 110: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

TheinnercircleofCaptureButtonwillbecomeblackonceit'spressed,andthengobacktobluewhenthemouseisreleased.Althoughit'sjustaminorvisualeffect,itdefinitelyimprovestheuserexperience.

"Donotfailtocommitanactofkindnessjustbecauseitissmallinscale."

TocompletethisQMLcameraapplication,weneedtoaddazoomcontrolaswedidfortheQt/C++camera.AddanewQMLfilenamedZoomControl.qml,whosecontentisshownasfollows:

importQtQuick2.3

Item{

propertyrealzoom:camera.opticalZoom*camera.digitalZoom

functionzoomControl(){

if(zoom>camera.maximumOpticalZoom){

camera.digitalZoom=zoom/camera.maximumOpticalZoom

camera.opticalZoom=camera.maximumOpticalZoom

}

else{

camera.digitalZoom=1.0

Page 111: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

camera.opticalZoom=zoom

}

}

Text{

id:indicator

anchors.fill:parent

horizontalAlignment:Text.AlignHCenter

verticalAlignment:Text.AlignVCenter

color:"darkgrey"

font.bold:true

font.family:"Segoe"

font.pointSize:20

style:Text.Raised

styleColor:"black"

}

Timer{

id:indicatorTimer

interval:2000

onTriggered:indicator.visible=false

}

MouseArea{

anchors.fill:parent

onWheel:{

if(wheel.angleDelta.y>0){

zoom+=1.0

if(zoom>camera.maximumOpticalZoom*

camera.maximumOpticalZoom){

zoom-=1.0

}

else{

zoomControl()

}

}

else{

zoom-=1.0

if(zoom<camera.maximumOpticalZoom*

camera.maximumOpticalZoom){

zoom+=1.0

}

else{

zoomControl()

}

}

indicator.text="X"+zoom.toString()

indicator.visible=true

indicatorTimer.running=true

}

}

}

First,wedeclarepropertyoftherealtypetostorethecurrentzoom,whoseinitial

Page 112: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

valueisthecamera'scurrentzoom,whichisitselfthemultiplicationofthecurrentdigitalandopticalzoom.ThisisfollowedbyaJavaScript-stylefunction,zoomControl.Asmentionedbefore,youcanuseJavaScriptinQMLanywhereseamlessly.ThisfunctionisidenticaltotheQt/C++slot,onZoomChanged,intheprevioustopic.

Then,thereisaTextelementusedtodisplaythecurrentzoomfunctiononscreen.ThesearejustsomevisualcustomizationsinsidetheTextelement,whichincludecenteringintheparentbysettingboththehorizontalandverticalalignments.

What'snextisaTimerelementthatcontrolsthevisibilityofText,similartothecontrollerofphotoPreview.

ThelastbutalsothetrickiestisMouseArea.Weusethemousewheeltocontrolthezoom,sothehandlerthatcangetthewheeleventisonWheel.Thewheel.angleDelta.yisthewheel,whichisrotatedtoaverticalorientation.Ifit'spositive,itgoesup;otherwise,itgoesdown.Itzoomsinwithapositivevalue,andzoomsoutwithnegativeone.YouhavetoensurethatthenewzoomiswithinthesupportedzoomrangeofcamerabeforeinvokingthezoomControlfunction.Afterthis,lettheTextindicatordisplayzoomandturnonTimersothatit'sonlyvisiblefor2seconds.Youcanalsoseethatthereisabuilt-infunctionfortherealelementtoconvertittostring,justliketheQString::numberfunctioninQt/C++.

Afterallthis,editmain.qmlandaddZoomControltotheapplication,asshowninthefollowingcode:

ZoomControl{

anchors.fill:viewfinder

}

BeawarethatZoomControlshouldfillinviewfinderinsteadofparent;otherwise,itmaygetoverlaidbyothercomponents,suchasviewfinder.

GivethisQMLcameraatestrunandcomparewhichoneisbetter.

Page 113: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

SummaryBytheendofthischapter,youshouldbeabletowriteapplicationsthatcanaccesscameradevicesineitherQt/C++orQML.What'smoreisthatyoushouldbeabletoutilizethestatusandmenubarintraditionaldesktopapplications,whicharehistoricallyimportantandcontinuetoplayacrucialroleasinteractivefunctionalwidgets.Inadditiontothis,don'tforgetthefiledialogandmessageboxsincetheymakeyourcodingworkeasier.Inthenextchapter,we'regoingtotalkaboutanadvancedtopic,plugins,whichisapopularwaytoextendlargeapplications.

Page 114: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

Chapter5.ExtendingPaintApplicationswithPluginsPluginsenableyoutomakeyourapplicationextendableandfriendlyforotherdevelopers.Therefore,inthischapter,we'llguideyouinhowtowritepluginsforQtapplications.ApaintapplicationdemonstratestherecipeforQt/C++.AsimpledemonstrationshowsyouhowtowriteaC++pluginforQML.Thetopicswewillcoverinthischapterarelistedasfollows:

DrawingviaQPainterWritingstaticpluginsWritingdynamicpluginsMergingpluginandmainprogramprojectsCreatingaC++pluginsforQMLapplications

DrawingviaQPainterBeforewegetstarted,letmeintroducetheQPainterclasstoyou.Thisclassperformslow-levelpaintingonwidgetsandotherpaintdevices.Infact,everythingdrawnonthescreeninaQtapplicationistheresultofQPainter.Itcandrawalmostanything,includingsimplelinesandalignedtext.Thankstothehigh-levelAPIsthatQthasprovided,it'sextremelyeasytousetheserichfeatures.

Qt'spaintsystemconsistsofQPainter,QPaintDevice,andQPaintEngine.Inthischapter,wewon'tneedtodealwiththelattertwo.Therelationsdiagramissketchedasfollows:

QPainterisusedtoperformdrawingoperations,whileQPaintDeviceisanabstractionofatwo-dimensionalspacethatcanbepaintedonbyusingQPainter.QPaintEngineprovidestheinterfacethatthepainterusestodrawontodifferenttypesofdevices.NotethattheQPaintEngineclassisusedinternallybyQPainterandQPaintDevice.It'salsodesignedtobehiddenfromprogrammersunlesstheycreatetheirowndevicetype.

Sobasically,whatweneedtoconcentrateonisQPainter.Let'screateanewproject

Page 115: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

anddosomeexercisesinit.Thenewpainter_demoprojectisaQtWidgetapplication.QuicklycreateitandaddanewC++CanvasclassthatinheritsfromQWidget.Canvasisourcustomizedwidgetwhoseheaderfileisshownasfollows:

#ifndefCANVAS_H

#defineCANVAS_H

#include<QWidget>

classCanvas:publicQWidget

{

Q_OBJECT

public:

explicitCanvas(QWidget*parent=0);

private:

QVector<QPointF>m_points;

protected:

voidpaintEvent(QPaintEvent*);

voidmousePressEvent(QMouseEvent*);

voidmouseMoveEvent(QMouseEvent*);

voidmouseReleaseEvent(QMouseEvent*);

};

#endif//CANVAS_H

TheQVectorclassisatemplateclassthatprovidesafastanddynamicarray.It'sfastbecausetheitemsarestoredinadjacentmemorylocations,whichmeansthattheindexingtimeisconstant.Here,westoretheQPointFelementsinm_points,whereQPointFisaclassthatdefinesapointusingafloatingpointprecision.

Inaprotectedscope,therearefoureventfunctions.We'refamiliarwiththesemouseevents.Theleadingone,whichisalsothenewone,isthepaintEventfunction.Sincewe'repaintingonthewidget,QPaintershouldonlybeusedinsidethepaintEventfunction.

Thedefinitionsofthefunctionsincanvas.cppareshownasfollows:

#include<QStyleOption>

#include<QPainter>

#include<QPaintEvent>

#include<QMouseEvent>

#include"canvas.h"

Canvas::Canvas(QWidget*parent):

QWidget(parent)

{

}

Page 116: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

voidCanvas::paintEvent(QPaintEvent*)

{

QPainterpainter(this);

QStyleOptionopt;

opt.initFrom(this);

this->style()->drawPrimitive(QStyle::PE_Widget,&opt,

&painter,this);

painter.setPen(QColor(Qt::black));

painter.setRenderHint(QPainter::Antialiasing);

painter.drawPolyline(m_points.data(),m_points.count());

}

voidCanvas::mousePressEvent(QMouseEvent*e)

{

m_points.clear();

m_points.append(e->localPos());

this->update();

}

voidCanvas::mouseMoveEvent(QMouseEvent*e)

{

m_points.append(e->localPos());

this->update();

}

voidCanvas::mouseReleaseEvent(QMouseEvent*e)

{

m_points.append(e->localPos());

this->update();

}

First,let'scheckwhat'sinsidethepaintEventfunction.ThefirstclauseistoinitializeaQPainterobject,whichusesthisasQPaintDevice.Well,thereisanalternatewaytoinitializeaQPainterclass,whichisdemonstratedhere:

QPainterpainter;

painter.begin(this);

painter.drawPolyline(m_points.data(),m_points.count());

painter.end();

Ifyouusethemethodshownintheprecedingcode,remembertocalltheend()functiontodestroypainter.Bycontrast,ifyouinitializeQPainterbyitsconstructor,thedestructorwillautomaticallycalltheend()function.However,theconstructorwon'treturnavalueindicatingwhetheritwasinitializedsuccessfullyornot.Thus,it'dbebettertochoosethelattermethodwhendealingwithanexternalQPaintDevicesuchasaprinter.

Aftertheinitialization,weuseQStyleOption,whichcontainsalltheinformationthat

Page 117: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

theQStylefunctionsneedtodrawagraphicalelementandmakeourcustomizedwidgetstyle-aware.WesimplyusetheinitFromfunctiontogetthestyleinformation.Then,wegettheQStylefunctionofourwidgetanddrawQStyle::PE_Widgetwithpainterusingthestyleoptionsspecifiedbyopt.Ifwedon'twritethesethreelines,wecan'tchangethewidgetdisplaystyle,suchasthebackgroundcolor.

Then,weletthepainteruseablackpentodrawananti-aliasingpolylineonthewidget.Here,anoverloadedsetPenfunctionisused.Thepainter.setPen(QColor(Qt::black))functionwillsetasolid-linestylepenwithawidthof1andthecolorinblack.Thepainter.setRenderHint(QPainter::Antialiasing)functionwillmakethedrawingsmooth.

NoteAsecondargument,bool,controlstherenderhint.It'struebydefault,whichmeansthatyouneedtoturnontherenderhint.Youcanturnoffarenderhintbypassingafalsevalue,though.

Alistoftheavailablerenderhintsareshownasfollows:

QPainter::Antialiasing

QPainter::TextAntialiasing

QPainter::SmoothPixmapTransform

QPainter::Qt4CompatiblePainting

Therearealsotwoobsoletehints:QPainter::HighQualityAntialiasingandQPainter::NonCosmeticDefaultPen.ThefirstoneisreplacedbyQPainter::AntialiasingandthesecondisuselessbecauseQPenisnon-cosmeticbydefaultnow.

Finally,thedrawPolylinefunctionwilldrawapolyline,whichismadefromthemousemovements,ontheCanvaswidget.ThefirstargumentisthepointertoaQPointForQPointarray,whilethesecondoneisthenumberofitemsinsidethatarray.

Speakingofmousemovements,threemouseeventfunctionsareusedtotrackthemouse.Infact,they'reprettyself-explanatory.Whenamousepresseventoccurs,purgethepointsarraybecauseit'sobviouslyanewpolylinenow,andthenaddthemousepositionbyinvokingalocalPos()function.ThelocalPos()functionwillreturnthepositionofthemouserelativetothewidgetoritemthatreceivedtheevent.AlthoughyoucangetaglobalpositionbythescreenPos()andglobalPos()function,inmostcases,weonlyneedalocalposition.Attheendoftheseeventfunctions,call

Page 118: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

update()torepaintthewidgettoshowthemousemovingpathasapolyline.

Now,editmainwindow.uiintheDesignmode.Removethestatusbarsincewewon'tuseitinthischapter,butkeepthemenubar.DragWidgettocentralWidgetandrenameitascanvas.Right-clickoncanvasandselectPromoteto…,andthenfillinCanvasinPromotedclassname.Now,clickonAdd,andthenonPromote.Youshouldn'tchecktheGlobalincludeboxbecausethecanvas.hheaderfileisinourprojectdirectoryinsteadoftheglobalincludedirectory.

InsideProperty,editstyleSheet,inputbackground-color:rgb(255,255,255);sothatthecanvashasawhitebackground.Then,changetheMainWindowclass'layouttoLayOutHorizontallyorLayOutVerticallysothatthecanvaswidgetcanfillthewholeframe.Giveyourapplicationarunnow;youshouldexpectasimplewhitepainterasfollows:

Thispainteristoosimpletoholdtheoldlines.WhileQtdoesn'tprovideanAPItopaintontheoldscene,QImagecangetusoutofthisdilemma.Inotherwords,whenthemousemoves,wepaintastrokeonaQImageobject,andthenpaintthisQImageobjectontoCanvas.

Thenewheaderfile,canvas.h,isasshownasfollows:

#ifndefCANVAS_H

#defineCANVAS_H

#include<QWidget>

classCanvas:publicQWidget

{

Page 119: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

Q_OBJECT

public:

explicitCanvas(QWidget*parent=0);

private:

QVector<QPointF>m_points;

QImageimage;

voidupdateImage();

protected:

voidpaintEvent(QPaintEvent*);

voidmousePressEvent(QMouseEvent*);

voidmouseMoveEvent(QMouseEvent*);

voidmouseReleaseEvent(QMouseEvent*);

voidresizeEvent(QResizeEvent*);

};

#endif//CANVAS_H

ThedifferencesincludethedeclarationofaQImageobject,image;privatememberfunction,updateImage();andareimplementedfunction,resizeEvent(QResizeEvent*).ThepaintEvent(QPaintEvent*)functionisalsochangedtodrawtheimageobjectinstead,whereastherearemoremodificationsinthecanvas.cppsourcefilethantheheaderfile,whosecontentisshownhere:

#include<QStyleOption>

#include<QPainter>

#include<QPaintEvent>

#include<QMouseEvent>

#include<QResizeEvent>

#include"canvas.h"

Canvas::Canvas(QWidget*parent):

QWidget(parent)

{

}

voidCanvas::paintEvent(QPaintEvent*e)

{

QPainterpainter(this);

QStyleOptionopt;

opt.initFrom(this);

this->style()->drawPrimitive(QStyle::PE_Widget,&opt,

&painter,this);

painter.drawImage(e->rect().topLeft(),image);

}

voidCanvas::updateImage()

{

QPainterpainter(&image);

Page 120: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

painter.setPen(QColor(Qt::black));

painter.setRenderHint(QPainter::Antialiasing);

painter.drawPolyline(m_points.data(),m_points.count());

this->update();

}

voidCanvas::mousePressEvent(QMouseEvent*e)

{

m_points.clear();

m_points.append(e->localPos());

updateImage();

}

voidCanvas::mouseMoveEvent(QMouseEvent*e)

{

m_points.append(e->localPos());

updateImage();

}

voidCanvas::mouseReleaseEvent(QMouseEvent*e)

{

m_points.append(e->localPos());

updateImage();

}

voidCanvas::resizeEvent(QResizeEvent*e)

{

QImagenewImage(e->size(),QImage::Format_RGB32);

newImage.fill(Qt::white);

QPainterpainter(&newImage);

painter.drawImage(0,0,image);

image=newImage;

QWidget::resizeEvent(e);

}

Let'slookintothemouseeventhandlers;aftertheoperationonm_points,theupdateImage()functioniscalledinsteadofupdate().InsidetheupdateImage()function,wecreateaQPainterobjectusingtheQImageobjectimageasQPaintDevicewhiletherestofthemarejustthesameasinpaintEvent.

Thereisanewmemberfunction,though,calledresizeEvent,whichisreimplementedfromQWidget.Asyoucanimagine,wechangetheunderlyingQImageobjectoncethewidgetsizechanges,whichcouldbeasaresultofwindowresizing.Therefore,wesimplypainttheoldimageontothenewone.Thismaycausethelossofapartoftheimageifthenewsizeissmallerthanthepreviousone.YoumaywishtoaddScrollAreatoMainWindowandmakeCanvasthechildwidgetofScrollArea.YoualreadyknowhowtodothatinQML,whileit'ssimilarinQt/C++.Therefore,justtakeitasanexerciseandimplementScrollAreaforthisapplication.

Page 121: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

WritingstaticpluginsTherearetwotypesofplugins:staticanddynamic.Staticpluginsarestaticallylinkedtotheexecutables,whilethedynamicpluginsareloadedatruntime.Dynamicpluginsexistasthe.dllor.sofiles,dependingontheplatform.Althoughthestaticpluginswillbebuiltasthe.libor.afiles,they'llbeintegratedintoanexecutablefilewhenthemainprogramgetscompiled.

Inthistopic,we'llgettoknowhowtowriteastaticplugintoextendtheapplication.Servingasanexternalplugin,itgainstheflexibilitytochangeitsinternalcodewhileit'sonlyrequiredtokeeptheinterfacecompatible.It'suptoyoutodecidewhethertheinterfaceshouldbemaintainedinthemainprogramorindifferentplugins.Inthisexample,we'llputtheinterface.hfileinthemainprogram,painter_demo.Thecontentofinterface.hisasfollows:

#ifndefINTERFACE_H

#defineINTERFACE_H

#include<QtPlugin>

#include<QPainterPath>

classInsertInterface

{

public:

virtual~InsertInterface(){}

virtualQStringname()const=0;

virtualQPainterPathgetObject(QWidget*parent)=0;

};

#defineInsertInterface_iid"org.qt-

project.Qt.PainterDemo.InsertInterface"

Q_DECLARE_INTERFACE(InsertInterface,InsertInterface_iid)

#endif//INTERFACE_H

Asyoucansee,wedeclareapurevirtualclass,InsertInterface.Inordertoavoiderrors,youhavetodeclareavirtualdestructor.Otherwise,thecompilermaycomplainandabortthecompilation.TheQPainterPathclassprovidesacontainerforcommon2Dpaintingoperations,includingellipseandtext.Hence,thereturntypeofgetObjectisQPainterPath,whichcanbeuseddirectlywheretheargument,QWidget,couldbeusefulifthereisanewlycreateddialogtogetanyinputfromtheuser.

Attheendofthisfile,wedeclareInsertInterfaceasaninterfacebytheQ_DECLARE_INTERFACEmacro,whereInsertInterface_iidistheidentifierforthe

Page 122: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

InsertInterfaceclass.Notethattheidentifiermustbeunique,soit'srecommendedthatyouuseaJava-stylenamingrule.

Now,weneedtocreateanewproject.NavigatetoLibraries|C++Library.Then,asshowninthefollowingscreenshot,selectQtPluginforTypeandkeepthisprojectinsidethemainprogramprojectfolderforthesakeofconvenienceoranyconcerns:

ClickonNextandchoosethesameQtkitsasthepainter_demoproject.Inthisexample,thebuilddirectoryissetinthesamedirectoryasthepainter_demoproject,whichisD:\Projects\build.Therefore,thebuilddirectoryofTextPluginisD:\Projects\build\TextPlugin-Qt_5_4_0_mingw491_32-DebugandD:\Projects\build\TextPlugin-Qt_5_4_0_mingw491_32-ReleaseforDebugandRelease,respectively.

NoteFurthermore,youcanchangeDefaultbuilddirectoryinTools|Options|Build&Run|General.Inthisbook,weuseD:/Projects/build/%{CurrentProject:Name}-%{CurrentKit:FileSystemName}-%{CurrentBuild:Name}

sothatallthebuildsareorganizedinoneplace.

Then,fillinTextPluginintheClassnamefield,asshowninthefollowingscreenshot:

Page 123: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

WeneedtoapplysomemodificationstotheTextPlugin.proprojectfile,asdisplayedhere:

QT+=coreguiwidgets

TARGET=TextPlugin

TEMPLATE=lib

CONFIG+=pluginstatic

DESTDIR=../plugins

SOURCES+=textplugin.cpp

INCLUDEPATH+=../

HEADERS+=textplugin.h

OTHER_FILES+=TextPlugin.json

Byaddingwidgets,wecanusesomeusefulclassessuchasQMessageBox.WealsoneedtoaddstatictoCONFIGtodeclarethisastaticpluginproject.Then,changetheDESTDIRvariableto../pluginssothatthepluginisinstalledtothepluginsdirectoryoutsidethebuildfolder.Lastly,weaddtheupperdirectory../toINCLUDEPATHsothatwecanincludetheinterface.hheaderfileinthissubproject.Thetextplugin.hfileisshownasfollows:

#ifndefTEXTPLUGIN_H

#defineTEXTPLUGIN_H

#include"interface.h"

Page 124: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

classTextPlugin:publicQObject,

publicInsertInterface

{

Q_OBJECT

Q_PLUGIN_METADATA(IID"org.qt-

project.Qt.PainterDemo.InsertInterface"FILE

"TextPlugin.json")

Q_INTERFACES(InsertInterface)

public:

QStringname()const;

QPainterPathgetObject(QWidget*parent);

};

#endif//TEXTPLUGIN_H

WeusetheQ_PLUGIN_METADATAmacrotospecifytheuniqueIID,whichisthesameastheonewedeclaredininterface.h,whereFILE"TextPlugin.json"canbeusedtocontainthemetadataforthisplugin.Inthiscase,wejustkeeptheTextPlugin.jsonfileintact.Then,theQ_INTERFACESmacrotellsthecompilerthatthisisapluginforInsertInterface.Inthepublicscope,therearejusttworeimplementedfunctions.Theirdefinitionsarelocatedinthetextplugin.cppsourcefile,whosecontentispastedasfollows:

#include<QInputDialog>

#include"textplugin.h"

QStringTextPlugin::name()const

{

returnQString("Text");

}

QPainterPathTextPlugin::getObject(QWidget*parent)

{

QPainterPathppath;

QStringtext=QInputDialog::getText(parent,QString("Insert

Text"),QString("Text"));

if(!text.isEmpty()){

ppath.addText(10,80,QFont("Cambria",60),text);

}

returnppath;

}

Thename()functionsimplyreturnsthenameofthisplugin,whichisTextinthiscase.AsforgetObject,itconstructsaQPainterPathclassthatcontainsthetextgivenbytheuserviaapop-updialog,andthenreturnstheQPainterPathobjecttothemainprogram.TheaddTextfunctionwilldrawthetextasasetofclosedsubpathscreated

Page 125: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

fromthefont,whilethefirsttwoargumentsdefinetheleftendofthebaselineforthistext.

Thisisitforthepluginproject.Now,justbuilditandyoushouldexpectalibTextPlugin.afiletobelocatedunderthepluginsdirectory,whilethepluginsdirectoryitselfshouldbelocatedintheparentdirectoryofyourproject'sbuildfolders,asshownhere:

Itdoesn'tmattermuchifyouputthefilesunderotherdirectories,althoughthismeansthatyouneedtodosomepathmodificationsrelevantlyafterwards.

Now,let'sgobacktothemainprogram'sproject,whichispainter_demointhisexample.Edititspainter_demo.proprojectfileandaddthefollowinglinetoit:

LIBS+=-L../plugins-lTextPlugin

TipTheworkingdirectoryduringcompilationisthebuilddirectoryinsteadoftheprojectsourcecodedirectory.

Then,editmainwindow.uiintheDesignmode;addamenunamedPluginstothemenubar,whoseobjectnameismenuPlugins.

Amongallthechangesmadeinthemainprogram,themodificationsfortheMainWindowclassaremaximum.Hereisthecodeofthenewmainwindow.hfile:

#ifndefMAINWINDOW_H

#defineMAINWINDOW_H

#include<QMainWindow>

namespaceUi{

classMainWindow;

}

classMainWindow:publicQMainWindow

{

Q_OBJECT

public:

Page 126: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

explicitMainWindow(QWidget*parent=0);

~MainWindow();

private:

Ui::MainWindow*ui;

voidloadPlugins();

voidgeneratePluginMenu(QObject*);

privateslots:

voidonInsertInterface();

};

#endif//MAINWINDOW_H

Stillnoclueaboutit?Well,itsmainwindow.cppsourcefileispastedhereaswell:

#include<QPluginLoader>

#include"mainwindow.h"

#include"ui_mainwindow.h"

#include"interface.h"

Q_IMPORT_PLUGIN(TextPlugin)

MainWindow::MainWindow(QWidget*parent):

QMainWindow(parent),

ui(newUi::MainWindow)

{

ui->setupUi(this);

loadPlugins();

}

MainWindow::~MainWindow()

{

deleteui;

}

voidMainWindow::loadPlugins()

{

foreach(QObject*plugin,QPluginLoader::staticInstances()){

generatePluginMenu(plugin);

}

}

voidMainWindow::generatePluginMenu(QObject*plugin)

{

InsertInterface*insertInterfacePlugin=

qobject_cast<InsertInterface*>(plugin);

if(insertInterfacePlugin){

QAction*action=newQAction(insertInterfacePlugin-

>name(),plugin);

connect(action,&QAction::triggered,this,

&MainWindow::onInsertInterface);

ui->menuPlugins->addAction(action);

Page 127: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

}

}

voidMainWindow::onInsertInterface()

{

QAction*action=qobject_cast<QAction*>(sender());

InsertInterface*insertInterfacePlugin=

qobject_cast<InsertInterface*>(action->parent());

constQPainterPathppath=insertInterfacePlugin-

>getObject(this);

if(!ppath.isEmpty()){

ui->canvas->insertPainterPath(ppath);

}

}

YoumayhavefiguredoutthattheQ_IMPORT_PLUGINmacroisusedtoimporttheplugin.Yes,itis,butonlyforstaticplugins.IntheloadPlugins()function,wewalkedthroughallthestaticplugininstancesandaddedthemtothemenubyinvokingthegeneratePluginMenufunction.

PluginsaretreatedasplainQOjbectobjectsatfirst,andthenyoucanuseqobject_casttoconvertthemtotheirownclasses.Theqobject_castclasswillreturnaNULLpointerifitfailed.Insidetheifstatement,thereisatricktousethepluginsuccessfullylater.InsteadofcallingasimplifiedandoverloadedaddActionfunction,wecanconstructQActionandaddittothemenu,becauseQActionwillhavethepluginasitsQObjectparent.Therefore,youcanseethatweconvertitsparenttotherelevantpluginclassintheonInsertInterfacefunction.Insidethisfunction,wecalltheinsertPainterPathfunctiontopainttheQPainterPathclassreturnedbythepluginoncanvas.Ofcourse,weneedtodeclareanddefinethisfunctionintheCanvasclass.Addthisstatementtothepublicdomainofthecanvas.hfile:

voidinsertPainterPath(constQPainterPath&);

Theprecedingcode'sdefinitionincanvas.cppisasfollows:

voidCanvas::insertPainterPath(constQPainterPath&ppath)

{

QPainterpainter(&image);

painter.drawPath(ppath);

this->update();

}

Theprecedingstatementsshouldbefamiliartoyouandthey'realsoself-explanatory.Now,buildandrunthisapplicationagain;don'tforgettochangethecurrentactiveprojectbacktopainter_demobyright-clickingonthepainter_demoprojectandselectingSet"painter_demo"asActiveProject.Whenitruns,clickonPlugins,selectText,inputPlugin!!inthepop-updialog,andconfirm.Then,you'llseethe

Page 128: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

text,Plugin!!,paintedonthecanvasasexpected.

Theexecutable'ssizegrowsaswellbecausewestaticallylinkedourTextPluginprojectfiletoit.Inadditiontothis,youhavetorebuildthemainprogramifyouchangedtheplugin.Otherwise,thenewlygeneratedpluginwon'tbelinkedtotheexecutableasitshould.

Page 129: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

WritingdynamicpluginsStaticpluginsprovideaconvenientwaytodistributeyourapplications.However,thisalwaysrequiresarebuildofthemainprogram.Bycontrast,dynamicpluginsaremuchmoreflexiblesincethey'relinkeddynamically.Thismeansthemainproject,whichispainter_demointhisexample,doesn'tneedtobebuiltwithdynamicpluginsnorisitrequiredtoreleaseitssourcecode.Instead,itonlyneedstoprovideaninterfaceandtheheaderfileofthatinterface,andthenscanthosedynamicpluginsatruntimesothattheycanbeloaded.

NoteDynamicpluginsarecommonlyseenincomplexapplications,especiallyincommercialsoftwaresuchasAdobeIllustrator.

Similartothestaticpluginwejustwrote,weneedtocreateanewQtPluginprojectandwe'llcallitEllipsePluginthistime.Althoughyoucanwriteanewinterfacealongwiththisplugin,herewewilljustfocusonplugin-relatedtopics.So,wejustreusetheInsertInterfaceclasswhiletheellipseplugin.proprojectfileisshownasfollows:

QT+=coreguiwidgets

TARGET=EllipsePlugin

TEMPLATE=lib

CONFIG+=plugin

DESTDIR=../plugins

SOURCES+=ellipseplugin.cpp\

ellipsedialog.cpp

HEADERS+=ellipseplugin.h\

ellipsedialog.h

OTHER_FILES+=EllipsePlugin.json

INCLUDEPATH+=../

FORMS+=ellipsedialog.ui

Don'tforgettochangetheDESTDIRandINCLUDEPATHvariablesintheellipseplugin.profilethough,they'rebasicallythesameasthepreviousTextPluginproject.

Ignoringthesourcefiles,forms,andsoon,it'sbasicallythesamethingwithonlythe

Page 130: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

removalofstaticinCONFIG.Theellipseplugin.hheaderfileisshownasfollows:

#ifndefELLIPSEPLUGIN_H

#defineELLIPSEPLUGIN_H

#include"interface.h"

classEllipsePlugin:publicQObject,

publicInsertInterface

{

Q_OBJECT

Q_PLUGIN_METADATA(IID"org.qt-

project.Qt.PainterDemo.InsertInterface"FILE

"EllipsePlugin.json")

Q_INTERFACES(InsertInterface)

public:

QStringname()const;

QPainterPathgetObject(QWidget*parent);

publicslots:

voidonDialogAccepted(qrealx,qrealy,qrealwid,qreal

hgt);

private:

qrealm_x;

qrealm_y;

qrealwidth;

qrealheight;

};

#endif//ELLIPSEPLUGIN_H

Asyoucanseeintheprecedingcode,wedeclarethatthisisapluginusingInsertInterfaceasthesameinTextPlugin,whereasthedifferenceisthedeclarationofanonDialogAcceptedslotfunctionandseveralprivatevariables.Accordingly,theellipseplugin.cppfileisshownasfollows:

#include"ellipsedialog.h"

#include"ellipseplugin.h"

QStringEllipsePlugin::name()const

{

returnQString("Ellipse");

}

QPainterPathEllipsePlugin::getObject(QWidget*parent)

{

m_x=0;

m_y=0;

Page 131: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

width=0;

height=0;

EllipseDialog*dlg=newEllipseDialog(parent);

connect(dlg,&EllipseDialog::accepted,this,

&EllipsePlugin::onDialogAccepted);

dlg->exec();

QPainterPathppath;

ppath.addEllipse(m_x,m_y,width,height);

returnppath;

}

voidEllipsePlugin::onDialogAccepted(qrealx,qrealy,qreal

wid,qrealhgt)

{

m_x=x;

m_y=y;

width=wid;

height=hgt;

}

Thereisnothingspecialaboutthename()function.Bycontrast,weusetheEllipseDialogcustomdialogtogetsomeinputsfromtheuser.Remembertoconnectallthesignalsandslotsassociatedwiththedialogbeforeexecutingtheexec()function;otherwise,theslotssimplywon'tbeconnected.Also,notethattheexec()functionwillblocktheeventloopandreturnonlyafterthedialogcloses,whichisprettyhandyforourpurposesbecausewecanusetheacceptedvalues,suchasm_xandm_y,toaddanellipsetoQPainterPath.

AsfortheEllipseDialogcustomdialogitself,itwascreatedbyaddinganewQtDesignerFormClassviaQtCreator.Sinceit'susedtoprovideaninterfacefortheusertospecifysomeparameters,weuseFormLayoutinthisdialog.AddQLabelandQDoubleSpinBox,assuggestedinthefollowingscreenshot:

Accordingly,theirobjectNamevaluesaretlXLabel,tlXDoubleSpinBox,tlYLabel,tlYDoubleSpinBox,widthLabel,widthDoubleSpinBox,heightLabel,andheightDoubleSpinBox.Youshouldalsochangethemaximumvalueto9999.99orsomethingbigenoughinthePropertypanelofQDoubleSpinBox.

Page 132: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

Inadditiontothis,alsonotethatthereisaremovalofthedefaultsignalandslotinSignals&SlotsEditor.Simplydeletetheaccepted()signalpairofbuttonBoxbecauseweneedamoreadvancedhandler.Inthisformclassheaderfile,ellipsedialog.h,wedeclareanewsignalandanewslot:

#ifndefELLIPSEDIALOG_H

#defineELLIPSEDIALOG_H

#include<QDialog>

namespaceUi{

classEllipseDialog;

}

classEllipseDialog:publicQDialog

{

Q_OBJECT

public:

explicitEllipseDialog(QWidget*parent=0);

~EllipseDialog();

signals:

voidaccepted(qreal,qreal,qreal,qreal);

private:

Ui::EllipseDialog*ui;

privateslots:

voidonAccepted();

};

#endif//ELLIPSEDIALOG_H

Theaccepted(qreal,qreal,qreal,qreal)signalherepassesthesevaluesbacktotheplugin,whiletheonAccepted()slothandlestheaccepted()signalemittedfrombuttonBox.Theyaredefinedintheellipsedialog.cppsourcefile,asshowninthefollowingcode:

#include"ellipsedialog.h"

#include"ui_ellipsedialog.h"

EllipseDialog::EllipseDialog(QWidget*parent):

QDialog(parent),

ui(newUi::EllipseDialog)

{

ui->setupUi(this);

connect(ui->buttonBox,&QDialogButtonBox::accepted,this,

&EllipseDialog::onAccepted);

}

Page 133: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

EllipseDialog::~EllipseDialog()

{

deleteui;

}

voidEllipseDialog::onAccepted()

{

emitaccepted(ui->tlXDoubleSpinBox->value(),ui-

>tlYDoubleSpinBox->value(),ui->widthDoubleSpinBox->value(),

ui->heightDoubleSpinBox->value());

this->accept();

}

Insidetheconstructor,connecttheaccepted()signalofbuttonBoxtotheonAccepted()advancedhandlerslot.Inthisslot,weemittheacceptedsignal,whichcontainsthevaluesthattheuserhasentered.Then,calltheaccept()functiontoclosethisdialog.

EllipsePluginisfinishedatthispoint.ClickontheBuildbuttoninthepaneltobuildthisproject.Youshouldexpecttheoutput,EllipsePlugin.dllonWindows,tobelocatedinthesamepluginsdirectoryasthepreviousTextPluginproject.

Tomakeuseofthisdynamicplugin,weneedafinalstep,whichistomakethemainprogramloadthedynamicplugin(s).WhatwehavetochangehereistheloadPlugins()functioninmainwindow.cpp:

voidMainWindow::loadPlugins()

{

foreach(QObject*plugin,QPluginLoader::staticInstances()){

generatePluginMenu(plugin);

}

//searchandloaddynamicplugins

QDirpluginDir=QDir(qApp->applicationDirPath());

#ifdefQ_OS_WIN

QStringdirName=pluginDir.dirName();

if(dirName.compare(QString("debug"),Qt::CaseInsensitive)

==0||dirName.compare(QString("release"),

Qt::CaseInsensitive)==0){

pluginDir.cdUp();

pluginDir.cdUp();

}

#endif

pluginDir.cd(QString("plugins"));

foreach(QStringfileName,pluginDir.entryList(QDir::Files))

{

QPluginLoader

loader(pluginDir.absoluteFilePath(fileName));

QObject*plugin=loader.instance();

Page 134: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

if(plugin){

generatePluginMenu(plugin);

}

}

}

InordertousetheQDirclass,youmayalsoneedtoincludethis:

#include<QDir>

TheQDirclasswillprovideaccesstodirectorystructuresandtheircontents,whichweusetolocateourdynamicplugins.TheqAppmacroisaglobalpointer,referringtothisveryapplicationinstance.It'sequivalenttotheQCoreApplication::instance()functionandQApplication::instance()fornon-GUIandGUIapplications,respectively.OnWindowsplatforms,ourpluginsdirectoryislocatedinthesecondupperfolderofthebuildpath.

Then,wejusttesteachfileinthepluginsdirectory,loadit,andgenerateapropermenuentryifit'saloadableplugin.Runthisapplicationagain;you'llhaveanEllipseentryinsidethePluginsmenu.Itworksasexpected.

Page 135: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

MergingpluginsandmainprogramprojectsItisatediousthingthatopensseveralprojectsandbuildstheminorder.Thisisnotabigdealgiventhatwehavejusttwopluginsandamainprogram.However,it'llbecomeaseriousinefficiencyissueoncethenumberofpluginsincrease.Therefore,itisabetterpracticetomergethepluginsintothemainprojectandgetthembuiltinaspecifiedordereverytimeweclickontheBuildbutton.It'stotallyfeasibleandiscommonlyseeninQtprojects.

Firstly,wemoveallthefilesinthepainter_demodirectory,exceptfortheEllipsePluginandTextPluginfolders,intoanewlycreatedmainfolder.

Then,renamethepainter_demo.protomain.prointhemainfolderwhilecreatinganewpainter_demo.proprojectfileoutsideinthepainter_demodirectory.Thisnewpainter_demo.proprojectfileneedstohavecontentsasshowninthefollowingcode:

TEMPLATE=subdirs

CONFIG+=ordered

SUBDIRS=TextPlugin\

EllipsePlugin\

main

Thesubdirsprojectisaspecialtemplate,whichmeansthatthisprojectfilewon'tgenerateanapplicationoralibrary.Instead,ittellsqmaketobuildsubdirectories.ByaddingorderedtoCONFIG,wecanensurethatthecompilingprocessfollowstheexactorderaccordingtoSUBDIRS.

Toaccomplishthis,weneedtomodifytheprojectfilesinthetwopluginsdirectories.ChangetheINCLUDEPATHvariabletothefollowingline:

INCLUDEPATH+=../main

Thischangeisobviousbecausewemovedallthesourcecodeintothemaindirectory.Ifwedon'tchangeINCLUDEPATH,thecompilerwillcomplainthatitcan'tfindtheinterface.hheaderfile.

Page 136: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

CreatingaC++pluginforQMLapplicationsIt'snottoodifficulttowriteapluginforQt/C++applications,whereasit'ssomewhatmorecomplextocreateapluginfortheQMLapplications.Theideaisthesame,andherewewilluseaverybasicexampletodemonstratethistopic.Basically,thisapplicationwillencodethetextinputasBase64anddisplayit.TheBase64encodingpartisimplementedintheC++plugin.

Thistime,we'regoingtocreatethepluginprojectfirst,andthencompletetheQMLpart.CreatingapluginprojectforaQMLapplicationsharesthesameprocedure.NavigatetoLibraries|C++Library,andthenselectQtPluginwiththenameasBase64Plugin.Itsprojectfile,Base64Plugin.pro,ispastedhere:

QT+=coreqml

TARGET=qmlbase64Plugin

TEMPLATE=lib

CONFIG+=plugin

DESTDIR=../imports/Base64

SOURCES+=base64.cpp\

base64plugin.cpp

HEADERS+=base64.h\

base64plugin.h

OTHER_FILES+=\

qmldir

WesetDESTDIRto../imports/Base64forthesakeofconvenience.Youcanchangethistosomeotherpath,butyoumayneedtomakesomerelevantchangeslatertobeabletoimportthisplugin.

ThisprojectconsistsoftwoC++classes.TheBase64classwilllaterbeexportedtoQML,whereasBase64PluginregisterstheBase64class.Theformerclass'base64.hheaderfileisasfollows:

#ifndefBASE64_H

#defineBASE64_H

#include<QObject>

classBase64:publicQObject

Page 137: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

{

Q_OBJECT

public:

explicitBase64(QObject*parent=0);

publicslots:

QStringget(QString);

};

#endif//BASE64_H

Thebase.cppcounterpartdefinesthegetfunction,asshowninthefollowingcode:

#include"base64.h"

Base64::Base64(QObject*parent):

QObject(parent)

{

}

QStringBase64::get(QStringin)

{

returnQString::fromLocal8Bit(in.toLocal8Bit().toBase64());

}

ThetrickypartisintheBase64Pluginclass,whichisnotidenticaltothepreviouspluginclass.Itsbase64plugin.hheaderfileisshownhere:

#ifndefBASE64PLUGIN_H

#defineBASE64PLUGIN_H

#include<QQmlExtensionPlugin>

classBase64Plugin:publicQQmlExtensionPlugin

{

Q_OBJECT

Q_PLUGIN_METADATA(IID"org.qt-

project.Qt.QmlExtensionInterface")

public:

voidregisterTypes(constchar*uri);

};

#endif//BASE64PLUGIN_H

WiththeQQmlExtensionPluginsubclass,we'reabletowriteourownQMLplugin.Infact,thisclassisusedtodeclaretheBase64classforQML.AlsonotethatsinceIIDinQ_PLUGIN_METADATAisfixed,youprobablydon'twanttochangeit.Asasubclass,it

Page 138: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

hastoreimplementtheregisterTypesfunction,whichsimplyregisterstheclass(es).Thedetaileddefinitionislocatedinthebaseplugin.cppfilewhosecontentsareasshowninthefollowingcode:

#include<QtQml>

#include"base64plugin.h"

#include"base64.h"

voidBase64Plugin::registerTypes(constchar*uri)

{

Q_ASSERT(uri==QLatin1String("Base64"));

qmlRegisterType<Base64>(uri,1,0,"Base64");

}

TheQ_ASSERTmacrowillensurethatthepluginislocatedinsidetheBase64directory.Ifnot,it'llprintawarningmessagecontainingthesourcecode,filename,andlinenumber.Notethaturi,whichisexpectedtobeBase64inthiscase,isthemodulenameforQML.Belowthisline,qmlRegisterTypeisatemplatefunctionwhereyouneedtoputtheclassname,Base64,insidebrackets.TheseargumentswillregistertheclasswithBase64astheQMLnamewithVersion1.0.

Alastpieceisneededtodeclarealoadableplugin,whichistheqmldirfile.Notethatithasnoextensionname.Thisfiledefinesthemodulenameandrelevantfilesinthedirectory.Hereisthecontent:

moduleBase64

pluginqmlbase64Plugin

Weneedtoputthisfileinthe../imports/Base64directory,whichistheDESTDIRofBase64Plugin.AlongwithafewlinesintheQMLapplicationproject'smain.cppfile,QMLcanthenimportapluginasitimportsanyotherQtQuickmodules.

It'stimetocreateanewQtQuickapplicationprojectnow.TheprojectnameissimplyQML_PluginandwemovetheBase64PluginclassintotheQML_Plugindirectory,whichenablestheQtCreatorsyntaxtohighlighttheBase64Pluginclass.Hereisthecontentofmain.qml:

importQtQuick2.3

importQtQuick.Controls1.2

importBase641.0

ApplicationWindow{

visible:true

width:180

height:100

title:qsTr("QMLPlugin")

Page 139: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

Base64{

id:b64

}

Column{

spacing:6

anchors{left:parent.left;right:parent.right;top:

parent.top;bottom:parent.bottom;leftMargin:6;rightMargin:

6;topMargin:6;bottomMargin:6}

Label{

text:"Input"

}

TextField{

id:input

width:parent.width

placeholderText:"Inputstringhere"

onEditingFinished:bt.text=b64.get(text)

}

Label{

text:"Base64Encoded"

}

TextField{

id:bt

readOnly:true

width:parent.width

}

}

}

RemembertostateimportBase641.0attheverybeginningofthecodesothatourplugincanbeloaded.Then,Base64isjustlikeotherQMLtypeswehaveusedbefore.IntheonEditingFinishedhandlerofinputTextField,weusethegetfunction,whichisintheBase64class,tosetbt.texttothecorrespondingBase64class-encodedstring.

YoumaywonderhowaQMLstringtypeisconvertedtoaQStringobject.Well,it'simplicitlyconvertedbetweenQMLandQt/C++.Thereareplentyoftheseconversionsforcommonly-seenQMLdatatypesandQtdataclasses.Fordetails,youcanlookattheQtdocumentationtoseethefulllist.

Anotherthingisthatweneedtochangemain.cpp,asmentionedbefore.SimilartotheQt/C++case,weusetheQDirclasstogetanapplicationdirectoryandchangeitto../imports.BeawarethatyoushoulduseaddImportPathinsteadofaddPluginPathtoadd../importstotheQMLengine'smodulesearchpath.ThisisbecauseweuseBase64asamodule,whichshouldbelocatedintheimportspath.Meanwhile,thepluginpathisfornativepluginsofimportedmodules,whicharestatedinqmldir.Thecontentofthemain.cppfileisasfollows:

#include<QApplication>

Page 140: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

#include<QDir>

#include<QQmlApplicationEngine>

intmain(intargc,char*argv[])

{

QApplicationapp(argc,argv);

QQmlApplicationEngineengine;

QDirpluginDir=app.applicationDirPath();

pluginDir.cdUp();

pluginDir.cdUp();

pluginDir.cd("imports");

engine.addImportPath(pluginDir.absolutePath());

engine.load(QUrl(QStringLiteral("qrc:/main.qml")));

returnapp.exec();

}

Inordertorunthisapplication,performthefollowingsteps:

1. BuildBase64Plugin.2. Copytheqmldirfileintothe../imports/Base64directory(theimportsfolder

shouldbelocatedinthesameplaceasplugins).3. BuildandruntheQML_Pluginproject.

YoucantestthisapplicationbyinputtinganystringinthefirstinputfieldandjustpressingEnter.Onescenarioforthisapplicationistoencodeyoure-mailaddresstoavoidawebspider,asshownhere:

Ifthemoduleisn'twelllocated,theapplicationwon'tshowupandit'llcomplainthatBase64isnotinstalled.Ifthathappens,makesureyouaddthecorrectpathinmain.cppandthereisaqmldirfileinsidetheBase64folder.

Page 141: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

SummaryItissomewhatdifficulttogetstartedonwritingplugins.However,aftersomebasicpractice,you'llfindthatit'sactuallyeasierthanitlooks.ForQtWidgetsapplications,pluginssimplyextendtheapplicationinaflexibleway.Meanwhile,theyenabledeveloperstodevisenewformsforQMLapplications.Wealsocoveredusingthesubdirsprojecttomanagemultiplesubprojects.Evenifyoudon'tplantowriteplugins,thischaptercoveredpainting-relatedstuffthatiscrucialforGUIapplicationdevelopment,includingQPainter,paintEvent,andresizeEvent.

Inthenextchapter,we'regoingtotalkaboutnetworkprogrammingandmultithreadinginQt.

Page 142: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

Chapter6.GettingWiredandManagingDownloadsNetworkmoduleshavebecomecrucialnowadaysandarealsoamust-havefeaturefordevelopmentframeworks;therefore,QtdoesprovideAPIsfornetworkprogramming.Sittight,we'regoingtogetwiredanddownloadfilesfromthenetwork.Inadditiontothis,threadingisincludedinthischapter,whichisavitalprogrammingskilltoavoidblocking.Thischapter'stopicsarelistedasfollows:

IntroducingQtnetworkprogrammingUtilizingQNetworkAccessManagerMakinguseoftheprogressbarWritingmultithreadedapplicationsManagingasystemnetworksession

IntroducingQtnetworkprogrammingQtsupportsnetworkprogrammingandprovideslotsofhigh-levelAPIstoeaseyourwork.QNetworkRequest,QNetworkReply,andQNetworkAccessManagerusecommonprotocolstoperformnetworkoperations.Qtalsoofferslower-levelclassestorepresentlowlevelnetworkconcepts.

Inthischapter,we'regoingtoutilizethehigh-levelAPIsthatQthasofferedtowriteadownloadertoretrievetheInternetfilesandsavethemtoyourdisk.AsImentionedearlier,theapplicationwillneedtheQNetworkRequest,QNetworkReply,andQNetworkAccessManagerclasses.

Firstly,allnetworkrequestsarerepresentedbytheQNetworkRequestclass,whichisageneralcontainerforinformationassociatedwitharequest,includingtheheaderandencryption.Currently,HTTP,FTP,andlocalfileURLsaresupportedforuploadinganddownloading.

Oncearequesthasbeencreated,theQNetworkAccessManagerclassisusedtodispatchitandemitssignals,reportingtheprogress.Then,itcreatesthereplytoanetworkrequest,representedbytheQNetworkReplyclass.Atthesametime,thesignalsprovidedbyQNetworkReplycanbeusedtomonitoreachreplyindividually.SomedeveloperswilldiscardthereferencetothereplyandusetheQNetworkAccessManagerclass'ssignalsforthatpurpose,though.Allrepliescanbehandledsynchronouslyorasynchronously,becauseQNetworkReplyisasubclassofQIODevice,whichmeansthatit'spossibletoimplementnonblockingoperations.

Page 143: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

Hereisadiagramthatdescribestherelationshipbetweentheseclasses:

Likewise,thenetwork-relatedstuffisofferedinthenetworkmodule.Tousethismodule,youneedtoedittheprojectfileandaddnetworktoQT.Now,createanewQtWidgetApplicationprojectandedittheprojectfile.InourDownloader_Demoexample,thedownloader_demo.proprojectfileisshownhere:

QT+=coreguinetwork

greaterThan(QT_MAJOR_VERSION,4):QT+=widgets

TARGET=Downloader_Demo

TEMPLATE=app

SOURCES+=main.cpp\

mainwindow.cpp\

downloader.cpp\

downloaddialog.cpp

HEADERS+=mainwindow.h\

downloader.h\

downloaddialog.h

FORMS+=mainwindow.ui\

downloaddialog.ui

Page 144: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

UtilizingQNetworkAccessManagerNow,we'regoingtodiscoverhowtowriteanapplicationthatisabletodownloadfilesfromotherlocations.Byotherlocations,wemeanthatyoucandownloadfilesfromalocalposition;itdoesn'thavetobeanInternetaddress,sincethelocalfileURLsaresupportedbyQtaswell.

Firstofall,let'screateaDownloaderclassthatwilluseQNetworkAccessManagertodothedownloadingworkforus.Thedownloader.hheaderfileispastedshownasfollows:

#ifndefDOWNLOADER_H

#defineDOWNLOADER_H

#include<QObject>

#include<QNetworkAccessManager>

#include<QNetworkRequest>

#include<QNetworkReply>

classDownloader:publicQObject

{

Q_OBJECT

public:

explicitDownloader(QObject*parent=0);

publicslots:

voiddownload(constQUrl&url,constQString&file);

signals:

voiderrorString(constQString&);

voidavailable(bool);

voidrunning(bool);

voiddownloadProgress(qint64,qint64);

private:

QNetworkAccessManager*naManager;

QStringsaveFile;

voidsaveToDisk(QNetworkReply*);

privateslots:

voidonDownloadFinished(QNetworkReply*);

};

#endif//DOWNLOADER_H

WeexposethedownloadslottogettheURLandthesavingtarget.Accordingly,saveFileisusedtostorethesavingtarget.Inadditiontothis,weuseannaManagerobjectoftheQNetworkAccessManagerclasstomanagethedownloadingprocess.

Page 145: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

Let'scheckthedefinitionsofthesefunctionsinthedownloader.cppfile.Inthefollowingconstructor,weconnectthenaManagerobject'sfinishedsignaltotheonDownloadFinishedslot.Therefore,whenanetworkconnectionisfinished,arelevantQNetworkReplyreferencewillbepassedviathissignal.

Downloader::Downloader(QObject*parent):

QObject(parent)

{

naManager=newQNetworkAccessManager(this);

connect(naManager,&QNetworkAccessManager::finished,this,

&Downloader::onDownloadFinished);

}

Accordingly,intheonDownloadFinishedslot,wehavetohandleQNetworkReplywithcaution.Ifthereisanyerror,whichmeansthatthedownloadhasfailed,weexposetheerrorString()functionbytheerrorStringsignal.Otherwise,wecallthesaveToDiskfunctiontosavethefiletothedisk.Then,weusedeleteLater()toreleasetheQNetworkReplyobjectsafely.AsstatedintheQtdocumentation,it'snotsafetousethedeletestatementdirectly;sinceit'sfinished,weemittheavailableandrunningsignals.Thosesignalswilllaterbeusedtochangetheuserinterface.

voidDownloader::onDownloadFinished(QNetworkReply*reply)

{

if(reply->error()!=QNetworkReply::NoError){

emiterrorString(reply->errorString());

}

else{

saveToDisk(reply);

}

reply->deleteLater();

emitavailable(true);

emitrunning(false);

}

InthesaveToDiskfunction,wejustimplementQFiletosaveallthedownloadeddatatothedisk.ThisisfeasiblebecauseQNetworkReplyinheritsfromQIODevice.Therefore,inadditiontothenetworkingAPIs,youcantreatQNetworkReplyasanormalQIODeviceobject.Inthiscase,usethereadAll()functiontogetalldata:

voidDownloader::saveToDisk(QNetworkReply*reply)

{

QFilef(saveFile);

f.open(QIODevice::WriteOnly|QIODevice::Truncate);

f.write(reply->readAll());

f.close();

}

Page 146: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

Finally,let'sseeinsidethedownloadfunctionthatwillbeusedbyMainWindowlater.Firstly,westorethesavedfiletosaveFile.Then,weconstructQNetworkRequestrequsingtheQUrlobject,url.Next,wesendreqtothenaManagerobjectofQNetworkAccessManager,whilesavingthereferencetothecreatedQNetworkManagerobjecttoreply.Afterthis,weconnectthetwodownloadProgresssignalstogether,whichissimplyexposingthedownloadProgresssignalofthereply.Atlast,weendupemittingtwosignals,indicatingtheavailabilityandrunningstatusrespectively.

voidDownloader::download(constQUrl&url,constQString

&file)

{

saveFile=file;

QNetworkRequestreq(url);

QNetworkReply*reply=naManager->get(req);

connect(reply,&QNetworkReply::downloadProgress,this,

&Downloader::downloadProgress);

emitavailable(false);

emitrunning(true);

}

WedescribedtheDownloaderclass.Now,we'regoingtoaddDownloadDialogbynavigatingtoQtDesigner|DialogwithButtonsBottom.ThisclassisusedtogettheURLandsavethepathfortheuser.Forthedesignofdownloaddialog.ui,weusethetwoQLineEditobjectstogettheURLandsavedpathrespectively.OneoftheobjectnamesisurlEdit,andtheotherissaveAsEdit.Inordertoopenafiledialogfortheusertochoosethesavinglocation,asaveAsButtonattributeofQPushButtonisaddedtotheright-handsideofsaveAsEdit.ThefollowingscreenshotshowsyouthelayoutofthisUIfile:

YouneedtochangethelayoutofthisdialogtoLayOutinaGrid.Inasimilarwayaswedidbefore,inordertopassthevaluestothemainwindow,weneedtodeletethedefaultacceptedsignalandslotconnectioninSignals&SlotsEditor.

Thecontentsofthisclass'sdownloaddialog.hheaderfileareshownhere:

#ifndefDOWNLOADDIALOG_H

#defineDOWNLOADDIALOG_H

#include<QDialog>

Page 147: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

namespaceUi{

classDownloadDialog;

}

classDownloadDialog:publicQDialog

{

Q_OBJECT

public:

explicitDownloadDialog(QWidget*parent=0);

~DownloadDialog();

signals:

voidaccepted(constQUrl&,constQString&);

private:

Ui::DownloadDialog*ui;

privateslots:

voidonButtonAccepted();

voidonSaveAsButtonClicked();

};

#endif//DOWNLOADDIALOG_H

Asyoucansee,anewsignalnamedacceptedisaddedtopasstheURLandsavethelocation.Besides,thetwoprivateslotsareusedtohandletheacceptedeventofthebuttonboxandthesaveAsButtonClickedsignal,respectively.

Thedefinitionsareinthedownloaddialog.cppsourcefile,whichisshownhere:

#include<QFileDialog>

#include"downloaddialog.h"

#include"ui_downloaddialog.h"

DownloadDialog::DownloadDialog(QWidget*parent):

QDialog(parent),

ui(newUi::DownloadDialog)

{

ui->setupUi(this);

connect(ui->buttonBox,&QDialogButtonBox::accepted,this,

&DownloadDialog::onButtonAccepted);

connect(ui->saveAsButton,&QPushButton::clicked,this,

&DownloadDialog::onSaveAsButtonClicked);

}

DownloadDialog::~DownloadDialog()

{

deleteui;

}

voidDownloadDialog::onButtonAccepted()

Page 148: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

{

emitaccepted(QUrl(ui->urlEdit->text()),ui->saveAsEdit-

>text());

this->accept();

}

voidDownloadDialog::onSaveAsButtonClicked()

{

QStringstr=QFileDialog::getSaveFileName(this,"SaveAs");

if(!str.isEmpty()){

ui->saveAsEdit->setText(str);

}

}

IntheconstructorofDownloadDialog,justconnectthesignalsandslots.IntheonButtonAcceptedslot,weemittheacceptedsignal,whichistopasstheURLandthesavingpath,whereatemporaryQUrlclassisconstructedusingthetextofurlEdit.Then,theacceptfunctionisinvokedtoclosethedialog.Meanwhile,intheonSaveAsButtonClickedslotfunction,weusethestaticfunctionprovidedbytheQFileDialogclasstoobtainthesavinglocation.DonothingiftheQStringreturnisempty;thismeansthattheusermayhaveclickedonCancelinthefiledialog.

Page 149: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

MakinguseoftheprogressbarAnintuitivewaytoindicatethedownloadingprogressisbyusingaprogressbar.InQt,itistheQProgressBarclassthatprovidesahorizontalorverticalprogressbarwidget.Itusesminimum,value,andmaximumtodeterminethecompletedpercentage.Thepercentageiscalculatedbytheformula,(value–minimum)/(maximum–minimum).We'llusethisusefulwidgetinourexampleapplicationbyperformingthefollowingsteps:

1. GobacktotheMainWindowclass.2. Editthemainwindow.uifileintheDesignmode.3. DragPushButtonandrenameitasnewDownloadButtonwithNewDownloadas

itstext.4. DragProgressBarjustbeneathnewDownloadButton.5. ChangethelayouttoLayOutVertically.6. UnchecktextVisibleintheprogressBarwidget'sproperty.

Thepushbutton,newDownloadButton,isusedtopopupDownloadDialogtogetanewdownloadtask.Weneedtoapplysomemodificationstomainwindow.h,assuggestedhere:

#ifndefMAINWINDOW_H

#defineMAINWINDOW_H

#include<QMainWindow>

#include"downloader.h"

#include"downloaddialog.h"

namespaceUi{

classMainWindow;

}

classMainWindow:publicQMainWindow

{

Q_OBJECT

public:

explicitMainWindow(QWidget*parent=0);

~MainWindow();

private:

Ui::MainWindow*ui;

Downloader*downloader;

DownloadDialog*ddlg;

privateslots:

voidonNewDownloadButtonPressed();

voidshowMessage(constQString&);

Page 150: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

voidonDownloadProgress(qint64,qint64);

};

#endif//MAINWINDOW_H

InordertousetheDownloaderandDownloadDialogclasses,wehavetoincludethemintheheaderfile.Then,wecanincludethemastheprivatepointers.Fortheprivateslots,onNewDownloadButtonPressedisusedtohandlethenewDownloadButtonclickedsignal.WhileshowMessageisaslotfunctionthatdisplaysthemessageonstatusbar,thelastone,onDownloadProgress,isusedtoupdatetheprogressbar.

Similarly,forthemainwindow.cppsourcefile,weconnectthesignalsandslotsintheconstructor,shownasfollows:

MainWindow::MainWindow(QWidget*parent):

QMainWindow(parent),

ui(newUi::MainWindow)

{

ui->setupUi(this);

ui->progressBar->setVisible(false);

downloader=newDownloader(this);

connect(ui->newDownloadButton,&QPushButton::clicked,this,

&MainWindow::onNewDownloadButtonPressed);

connect(downloader,&Downloader::errorString,this,

&MainWindow::showMessage);

connect(downloader,&Downloader::downloadProgress,this,

&MainWindow::onDownloadProgress);

connect(downloader,&Downloader::available,ui-

>newDownloadButton,&QPushButton::setEnabled);

connect(downloader,&Downloader::running,ui->progressBar,

&QProgressBar::setVisible);

}

Beforebeginningtocreatetheseconnections,weneedtohidetheprogressbarandcreateanewDownloaderclass,usingMainWindowastheQObjectparent.Meanwhile,intheseconnections,thefirstoneistoconnectthenewDownloadButtonclickedsignal.Then,weconnecttheerrorStringsignalofdownloadertoshowMessage,whichenablesthestatusbartoshowtheerrormessagedirectly.Next,weconnectthedownloadProgresssignaltoouronDownloadProgresshandler.Asfortheavailableandrunningsignals,they'reconnectedtocontroltheavailabilityandvisibilityofnewDownloadButtonandprogressBar,respectively.

InsidetheonNewDownloadButtonPressedslotfunction,weconstructaDownloadDialogobject,ddlg,thenconnecttheacceptedsignalofDownloadDialogtotheDownloaderclass'sdownloadslot.Then,useexectorunthedialogandblocktheeventloop.

Page 151: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

Afterthis,wecalldeleteLatertosafelyreleasetheresourceallocatedforddlg.

voidMainWindow::onNewDownloadButtonPressed()

{

ddlg=newDownloadDialog(this);

connect(ddlg,&DownloadDialog::accepted,downloader,

&Downloader::download);

ddlg->exec();

ddlg->deleteLater();

}

AsfortheshowMessageslotfunction,itsimplycallstheshowMessagefunctionofstatusBarwithathreesecondtimeout,asshownhere:

voidMainWindow::showMessage(constQString&es)

{

ui->statusBar->showMessage(es,3000);

}

Atlast,wecanupdatetheprogressbarviatheonDownloadProgressfunction,whichisshowninthefollowingcode.Sincetheminimumvalueis0bydefault,wedon'tneedtochangeit.Instead,wechangethemaximumvaluetothetotalbytesofthedownload,andvaluetothecurrentdownloadedbytes.Notethatifthetotalsizeisunknown,thenthevalueofthetotalsizeis-1,whichwillhappentomaketheprogressbardisplayinabusystyle.

voidMainWindow::onDownloadProgress(qint64r,qint64t)

{

ui->progressBar->setMaximum(t);

ui->progressBar->setValue(r);

}

Now,givetheapplicationarunandclickontheNewDownloadbutton.TheAddNewDownloaddialogwillpopup,whereyoucanaddanewdownloadtaskasshownhere:

ClickonOK,ifthereisnoerror;aprogressbarisexpectedtoshowupanddisplaythecurrentdownloadprogress,shownasfollows:

Page 152: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

Asyoucansee,theNewDownloadbuttonisnotenablednow,sinceitisassociatedwiththeavailablesignalofdownloader.Besides,theprogressbarwon'tevenshowifdownloaderisn'trunning.

Whilethisdownloaderdemostilllacksabasicfunction,whichistocanceldownloading,itis,infact,easytoimplement.ThereisaslotfunctioncalledabortintheQNetworkReplyclass.YoumayhavetostorethereferencetoQNetworkReplyandthencallabortifsomebuttoninMainWindowisclicked.Thiswon'tbedemonstratedhere.Ithasbeenleftuptoyoutopracticeonyourown.

Page 153: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

WritingmultithreadedapplicationsIbetmultithreadorthreadingisn'tunfamiliartoyou.UsingotherthreadssavestheGUIapplicationfromfreezing.Iftheapplicationrunsonasinglethread,it'llgetstuckifthereit'sasynchronoustime-consumingoperation.Multiplethreadsmakeapplicationrunningmuchsmoother.AlthoughmostoftheQtNetworkAPIsarenonblocking,itisnotthatdifficulttopracticeonit.

QtprovidesaQThreadclasstoimplementthreadingonallsupportedplatforms.Inotherwords,wedon'tneedtowriteplatform-specificcodeutilizingPOSIXThreadsoraWin32API.Instead,QThreadprovidesaplatform-independentwaytomanagethreads.AQThreadobjectmanagesathreadwithintheprogram,whichbeginsexecutinginrun()andendswhencallingquit()orexit().

Forsomehistoricalreason,it'sstillpossibletosubclassQThreadandputtheblockingortime-consumingcodeinthereimplementedrun()function.However,it'sconsideredanincorrectpracticeandisnotrecommendedtodoso.TherightwayistouseQObject::moveToThread,whichwillbedemonstratedlater.

We'regoingtoputtheDownloader::downloadfunctionintoanewthread.Infact,it'stheQNetworkAccessManager::getfunctionthatwillbemovedontoanotherthread.Let'screateanewC++class,DownloadWorker,whosedownloadworker.hheaderfileispastedasfollows:

#ifndefDOWNLOADWORKER_H

#defineDOWNLOADWORKER_H

#include<QObject>

#include<QNetworkReply>

#include<QNetworkRequest>

#include<QNetworkAccessManager>

classDownloadWorker:publicQObject

{

Q_OBJECT

publicslots:

voiddoDownload(constQUrl&url,QNetworkAccessManager*nm);

signals:

voiddownloadProgress(qint64,qint64);

};

#endif//DOWNLOADWORKER_H

Theconstructorisremovedfromthecodebecausewecan'tmakeachildobjectthat

Page 154: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

willbeinanotherthread.ThisisalmosttheonlylimitationofQThread.Incontrasttothis,youcanconnectsignalsandslotsbetweendifferentthreadswithoutanyproblems.

Don'tsplitparentandchildrenbetweenthreads.Parentobjectsandchildrenobjectscanonlybeinthesamethread.

WedeclarethedoDownloadslotfunctiontodotheQNetworkAccessManager::getfunctionworkforus.Ontheotherhand,thedownloadProgresssignalisusedtoexposethedownloadProgresssignalofQNetworkReplyaswedid.Thecontentsofdownloadworker.cppisshownasfollows:

#include"downloadworker.h"

voidDownloadWorker::doDownload(constQUrl&url,

QNetworkAccessManager*nm)

{

QNetworkRequestreq(url);

QNetworkReply*reply=nm->get(req);

connect(reply,&QNetworkReply::downloadProgress,this,

&DownloadWorker::downloadProgress);

}

Theprecedingcodeisanexampleofasimpleworkerclass.Now,wehavetochangetheDownloaderclasstousetheDownloadWorkerclass.TheheaderfileoftheDownloaderclass,downloader.h,needsafewmodifications,shownhere:

#ifndefDOWNLOADER_H

#defineDOWNLOADER_H

#include<QObject>

#include<QNetworkAccessManager>

#include<QNetworkRequest>

#include<QNetworkReply>

#include<QThread>

#include"downloadworker.h"

classDownloader:publicQObject

{

Q_OBJECT

public:

explicitDownloader(QObject*parent=0);

~Downloader();

publicslots:

voiddownload(constQUrl&url,constQString&file);

signals:

voiderrorString(constQString&);

voidavailable(bool);

Page 155: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

voidrunning(bool);

voiddownloadProgress(qint64,qint64);

private:

QStringsaveFile;

QNetworkAccessManager*naManager;

DownloadWorker*worker;

QThreadworkerThread;

voidsaveToDisk(QNetworkReply*);

privateslots:

voidonDownloadFinished(QNetworkReply*);

};

#endif//DOWNLOADER_H

Asyoucansee,wehavedeclaredanewprivatemember,workerThread,whichisatypeofQThread.Also,aDownloadWorkerobjectworkerhasbeendeclaredaswell.Therearemorechangesinthedownloader.cppsourcefile,asdisplayedhere:

#include<QFile>

#include"downloader.h"

Downloader::Downloader(QObject*parent):

QObject(parent)

{

naManager=newQNetworkAccessManager(this);

worker=newDownloadWorker;

worker->moveToThread(&workerThread);

connect(naManager,&QNetworkAccessManager::finished,this,

&Downloader::onDownloadFinished);

connect(&workerThread,&QThread::finished,worker,

&DownloadWorker::deleteLater);

connect(worker,&DownloadWorker::downloadProgress,this,

&Downloader::downloadProgress);

workerThread.start();

}

Downloader::~Downloader()

{

workerThread.quit();

workerThread.wait();

}

voidDownloader::download(constQUrl&url,constQString

&file)

{

saveFile=file;

worker->doDownload(url,naManager);

emitavailable(false);

Page 156: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

emitrunning(true);

}

voidDownloader::onDownloadFinished(QNetworkReply*reply)

{

if(reply->error()!=QNetworkReply::NoError){

emiterrorString(reply->errorString());

}

else{

saveToDisk(reply);

}

reply->deleteLater();

emitavailable(true);

emitrunning(false);

}

voidDownloader::saveToDisk(QNetworkReply*reply)

{

QFilef(saveFile);

f.open(QIODevice::WriteOnly|QIODevice::Truncate);

f.write(reply->readAll());

f.close();

}

Intheconstructor,wewillcreateanewDownloadWorkerclass,andmoveittoanotherthread,workerThread.ByconnectingthefinishedsignalofworkerThreadtothedeleteLaterfunctionofworker,theresourcesofworkercanbedeletedsafelyaftertheexitofworkerThread.Then,weneedtoexposedownloadProgressagain,sinceit'smovedintoworker.Atlast,wecallthestart()function,tostartworkerThread.

Asareverseoperation,wecallthequit()functiontoexitworkerThreadandthenusewait()toensureitquitssuccessfully.

SincealotofcodehasbeenmovedintothedoDownloadfunctionofworker,weonlyneedtocalldoDownloadofworkerhere.Infact,thefunctioncallingisinter-thread,whichmeansthatthemainthreadwon'tbeblockedbythatstatement.

Sincegetisnotblocking,youmaynotfeelthedifference.However,I'msureyouhavesomeapplicationsthathavefrozen,whichthereforeneedtobemodifiedtoadapttoQThread.Alwaysremembertoputonlythebackgroundblockingoperationsinanotherthread.ThisismainlybecausetheseoperationsareeasilyseparatedfromGUIintosingleobjectswithoutparentsorchildren.Duetothislimitation,almostalltheGUIobjectsmustbeinthesamethread,whichisthemainthreadinmostcases.

Page 157: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

ManagingasystemnetworksessionInadditiontonetworkingapplications,Qtalsoprovidesyouwithcross-platformAPIstocontrolnetworkinterfacesandaccesspoints.Althoughit'snotverycommontocontrolthenetworkstate,therearesomecertainsituationswhereit'srequiredtodothis.

First,I'dliketointroduceQNetworkConfigurationManagertoyou.Thisclassmanagesthenetworkconfigurationsprovidedbythesystem.Itenablesyouaccesstothem,aswellastodetectthesystem'scapabilitiesduringruntime.ThenetworkconfigurationispresentedbytheQNetworkConfigurationclass,whichabstractsasetofconfigurationoptionsconcerninghowanetworkinterfacehastobeconfiguredinordertoconnecttothetargetnetwork.Tocontrolthenetworksession,youneedtousetheQNetworkSessionclass.Thisclassprovidesyouwithcontroloverthesystem'saccesspointsandenablessessionmanagement.ItalsoenablesyoutocontrolnetworkinterfacesthatarerepresentedbytheQNetworkInterfaceclass.Tohelpyoufigureoutthisrelationship,adiagramisshownhere:

Asyoucansee,thestructureissimilartoQNetworkAccessManager,QNetworkReply,andQNetworkRequest.Especially,thereisanothermanagerclass.Let'sseehowtodealwiththeseclassesinpractice.

CreateanewQtWidgetsApplicationprojectasusual.TheexampleregardingthistopiciscalledNetworkManager_Demo.RemembertoaddnetworktoQtinyourprojectfile,aswedidinthepreviousexample.Then,editmainwindow.uiintheDesignmodeandperformthefollowingsteps:

1. Removethestatusbar,menubar,andtoolbarsincewedon'tneedtheminthisapplication.

2. AddListView(undertheItemViews(Model-Based)category).

Page 158: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

3. DragVerticalLayouttotherightoflistView.4. ChangeLayoutinMainWindowtoLayOutHorizontally.5. DragLabelintoverticalLayoutandrenameitasonlineStatus.6. DragProgressBarintoverticalLayout.Changeitsmaximumvalueto0and

unchecktextVisiblesothatitcanbeusedasabusyindicator.7. AddthreePushButtonbuttons;Refresh,Connect,andDisconnect;beneath

theprogressbar.TheirobjectnamesarerefreshButton,connectButton,anddisconnectButton,respectively.

8. Atlast,dragVerticalSpacerbetweenprogressBarandonlineStatustoseparatethem.

Asusual,weneedtodosomedeclarationsinmainwindow.hheaderfileasshownhere:

#ifndefMAINWINDOW_H

#defineMAINWINDOW_H

#include<QMainWindow>

#include<QNetworkConfigurationManager>

#include<QNetworkConfiguration>

#include<QNetworkSession>

#include<QStandardItemModel>

namespaceUi{

classMainWindow;

}

classMainWindow:publicQMainWindow

{

Q_OBJECT

public:

explicitMainWindow(QWidget*parent=0);

~MainWindow();

private:

Ui::MainWindow*ui;

QNetworkConfigurationManager*networkConfManager;

QStandardItemModel*confListModel;

privateslots:

voidonOnlineStateChanged(boolisOnline);

voidonConfigurationChanged(constQNetworkConfiguration

&config);

voidonRefreshClicked();

voidonRefreshCompleted();

voidonConnectClicked();

voidonDisconnectClicked();

};

#endif//MAINWINDOW_H

Page 159: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

Inthiscase,weonlyutilizetheQNetworkConfigurationManager,QNetworkConfiguration,andQNetworkSessionclassestomanagethesystemnetworksessions.Therefore,weneedtoincludetheminanappropriatelocation.

NoteNotethatweonlyneedtodeclareaprivatemember,inthiscasenetworkConfManager,oftheQNetworkConfigurationManagerclass,becausetheQNetworkConfigurationcanberetrievedfromthismanager,whileQNetworkSessionisboundtoQNetworkConfiguration.

AsforQStandardItemModel,rememberthemodel/viewstuffinChapter3,CookinganRSSReaderwithQtQuick.TheonlydifferencebetweenthatchapterandthisoneisthatwewroteQMLintheformer.However,weareusingaC++applicationinthischapter.Theysharethesameconcept,though,andit'sjustthetoolthatchanges.QStandardItemModel*confListModelistheexactmodeloflistViewintheUIfile.

Last,butnotleast,isthedeclarationofsomeslots.Apartfromthebuttonclickhandlers,thefirsttwoareusedtomonitorthenetworksystem.Thisisexplainedlater.

Let'seditthemainwindow.cppfileandtakealookattheconstructorofMainWindow:

MainWindow::MainWindow(QWidget*parent):

QMainWindow(parent),

ui(newUi::MainWindow)

{

ui->setupUi(this);

networkConfManager=newQNetworkConfigurationManager(this);

confListModel=newQStandardItemModel(0,1,this);

ui->listView->setModel(confListModel);

ui->progressBar->setVisible(false);

connect(networkConfManager,

&QNetworkConfigurationManager::onlineStateChanged,this,

&MainWindow::onOnlineStateChanged);

connect(networkConfManager,

&QNetworkConfigurationManager::configurationChanged,this,

&MainWindow::onConfigurationChanged);

connect(networkConfManager,

&QNetworkConfigurationManager::updateCompleted,this,

&MainWindow::onRefreshCompleted);

connect(ui->refreshButton,&QPushButton::clicked,this,

&MainWindow::onRefreshClicked);

Page 160: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

connect(ui->connectButton,&QPushButton::clicked,this,

&MainWindow::onConnectClicked);

connect(ui->disconnectButton,&QPushButton::clicked,this,

&MainWindow::onDisconnectClicked);

onOnlineStateChanged(networkConfManager->isOnline());

onRefreshClicked();

}

WeconstructQNetworkConfigurationManagerwiththisobject,alsoknownasMainWindowasitsQObjectparent.Then,welookattheconstructionofconfListModel.Theargumentsarethecountofrow,thecountofcolumn,andtheQObjectparent,whichisthisasusual.WewilluseonlyonecolumnbecauseweuseListViewtodisplaythedata.IfyouuseTableView,youwillprobablyusemorecolumns.Then,webindthismodeltolistViewofui.Afterthis,wehideprogressBarbecauseit'sabusyindicator,whichonlyshowsupwhenthereisworkrunning.Therewillbeseveralconnectstatementsbeforewecalltwomemberfunctionsexplicitly.Amongthem,youmaywanttolookintothesignalsofQNetworkConfigurationManager.TheonlineStateChangedsignalisemittediftheonlinestatusofthesystemischanged,thatis,offlinefromonline.TheconfigurationChangedsignalisemittedwheneverthestateofQNetworkConfigurationischanged.OnceQNetworkConfigurationManagerfinishedupdateConfigurations,theupdateCompletedsignalwillbeemitted.Intheendoftheconstructor,wecallonOnlineStateChangeddirectlyinordertosetupthetextofonlineStatus.Similarly,callingonRefreshClickedenablesanapplicationtoscanforallthenetworkconfigurationsatthestart.

Asmentionedbefore,theonOnlineStateChangedfunctionisusedtosetuponlineStatus.It'lldisplayOnlineifthesystemisconsideredtobeconnectedtoanotherdeviceviaanactivenetworkinterface;otherwise,it'lldisplayOffline.Thisfunction'sdefinitionisshownasfollows:

voidMainWindow::onOnlineStateChanged(boolisOnline)

{

ui->onlineStatus->setText(isOnline?"Online":"Offline");

}

InsidetheonConfigurationChangedslotfunction,whichisshowninthefollowingcode,wechangetheitem'sbackgroundcolortoindicatewhetheraconfigurationisactiveornot.WeusethefindItemsfunctiontogetitemList,whichcontainsonlysomeQStandardItemthatmatchesconfig.name()exactly.However,theconfigurationnamemaynotbeunique.Thisiswhyweuseaforeachlooptocomparetheidentifierofconfig,whichisauniquestring,wherethedatafunctionisusedtoretrievethespecificdatawhosetypeisQVariant.Then,weusetoStringtocastitbacktoQString.QStandardItemenablesussetmultipledataintooneitem.

Page 161: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

voidMainWindow::onConfigurationChanged(const

QNetworkConfiguration&config)

{

QList<QStandardItem*>itemList=confListModel-

>findItems(config.name());

foreach(QStandardItem*i,itemList){

if(i-

>data(Qt::UserRole).toString().compare(config.identifier())==

0){

if

(config.state().testFlag(QNetworkConfiguration::Active)){

i->setBackground(QBrush(Qt::green));

}

else{

i->setBackground(QBrush(Qt::NoBrush));

}

}

}

}

ThismeansthatwestoreidentifierasaQt::UserRoledata.Itwon'tbedisplayedonthescreen;instead,itservesasaspecificdatacarrier,whichturnsouttobeveryhelpfulinthiscase.Thus,afterthis,ifit'sactive,wesetthebackgroundcolortogreen;otherwise,usenobrush,whichmeansadefaultbackground.NotethatthestatefunctionofQNetworkConfigurationreturnsStateFlags,whichisactuallyaQFlagtemplateclass,wherethebestpracticeistocheckwhetherornotaflagissetistousethetestFlagfunction.

Let'schecktheonRefreshClickedfunction,whichisshowninthefollowingcodebeforeonRefreshCompleted.It'llcallupdateConfigurationsoftheQNetworkConfigurationManager*networkConfManager.Thisfunctionisatimeconsumingone,especiallyifitneedstoscanWLAN.Therefore,weshowprogressBartotelluserstobepatientanddisablerefreshButton,sinceit'srefreshing.

voidMainWindow::onRefreshClicked()

{

ui->progressBar->setVisible(true);

ui->refreshButton->setEnabled(false);

networkConfManager->updateConfigurations();

}

Whentheupdatehasbeencompleted,theupdateCompletedsignalisemittedandtheonRefreshCompletedboundslotisexecuted.Checkthefollowingfunctionshownhere,whereweneedtopurgethelist.However,insteadofcallingtheclearfunction,weuseremoveRows,whichwouldsparethecolumn.Ifyou'recallingclear,bewaretoaddthecolumnback;otherwise,thereisliterallynocolumn,whichmeansthatthereisnoplacetoputtheitem.Intheforeachloop,weaddalltheconfigurationsthat

Page 162: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

networkConfManagerhasfoundtoconfListModel.AsImentionedpreviously,weusethenameasdisplayingtext,whilewesetitsidentifierasahiddenuserroledata.Aftertheloop,hideprogressBarastherefreshingisfinished,andthenenablerefreshButton.

voidMainWindow::onRefreshCompleted()

{

confListModel->removeRows(0,confListModel->rowCount());

foreach(QNetworkConfigurationc,networkConfManager-

>allConfigurations()){

QStandardItem*item=newQStandardItem(c.name());

item->setData(QVariant(c.identifier()),Qt::UserRole);

if(c.state().testFlag(QNetworkConfiguration::Active)){

item->setBackground(QBrush(Qt::green));

}

confListModel->appendRow(item);

}

ui->progressBar->setVisible(false);

ui->refreshButton->setEnabled(true);

}

Theremainingtwoarehandlerstotheconnectanddisconnectbuttons.ForconnectButton,weshowprogressBarbecauseitmaytakealongtimetogettheIPaddressfromtherouter.Then,wegetidentifierfromthedataofconfListModeldirectlyandsaveitasQStringident,wherethecurrentIndexfunctionoflistViewwillreturnthecurrentQModelIndexoftheview.Byusingthisindex,wecangetthecurrentlyselecteddatafromthemodel.Then,weconstructQNetworkConfigurationfromidentbycallingconfigurationFromIdentifierofnetworkConfManager.TheQNetworkSessionsessionisconstructedusingQNetworkConfiguration.Atlast,openthisnetworksessionandwaitfor1,000milliseconds.Then,calldeleteLatertosafelyreleasethesession.Also,hideprogressBarafteralltheseworksintheend.

voidMainWindow::onConnectClicked()

{

ui->progressBar->setVisible(true);

QStringident=confListModel->data(ui->listView-

>currentIndex(),Qt::UserRole).toString();

QNetworkConfigurationconf=networkConfManager-

>configurationFromIdentifier(ident);

QNetworkSession*session=newQNetworkSession(conf,this);

session->open();

session->waitForOpened(1000);

session->deleteLater();

ui->progressBar->setVisible(false);

}

voidMainWindow::onDisconnectClicked()

{

QStringident=confListModel->data(ui->listView-

>currentIndex(),Qt::UserRole).toString();

Page 163: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

QNetworkConfigurationconf=networkConfManager-

>configurationFromIdentifier(ident);

QNetworkSession*session=newQNetworkSession(conf,this);

if(networkConfManager-

>capabilities().testFlag(QNetworkConfigurationManager::SystemS

essionSupport)){

session->close();

}

else{

session->stop();

}

session->deleteLater();

}

AsfordisconnectButton,theonDisconnectClickedhandlerwilldothereverse,whichistostopthenetworksession.ThefirstthreelinesareidenticaltothoseinonConnectClicked.However,wethenneedtotestwhethertheplatformsupportsout-of-processsessions.AsstatedintheQtdocumentation,theresultofcallingclosewillbeasfollows:

voidQNetworkSession::close()[slot]

Decreasesthesessioncounterontheassociatednetworkconfiguration.Ifthesessioncounterreacheszerotheactivenetworkinterfaceisshutdown.Thisalsomeansthatstate()willonlychangefromConnectedtoDisconnectedifthecurrent

sessionwasthelastopensession.

However,iftheplatformdoesn'tsupportout-of-processsessions,theclosefunctionwon'tstoptheinterface,inwhichcaseweneedtousestopinstead.

Therefore,wecallthecapabilitiesfunctionofnetworkConfManagertocheckwhetherithasSystemSessionSupport.Callcloseifitdoes,otherwisecallstop.Then,wejustcalldeleteLatertosafelyreleasethesession.

Now,runthisapplication,andyou'llexpectitworksasthefollowingscreenshot:

Page 164: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

OnWindows,thenetworkarchitectureisdifferentfromthatoftheworldofUnix.So,youmayfindsomeoddconfigurationsinthelist,suchasTeredoTunnelingPseudo-Interfaceinthescreenshot.Don'tworryabouttheseconfigurationsandjustignorethem!Also,thereisnoQtAPItoallowyoutoconnecttoanewlydiscoveredencryptedWi-Fiaccesspoint.ThisisbecausethereisnoimplementationinplacetoaccesstheWLANsystempasswords.Inotherwords,itcanonlybeusedtocontrolthenetworksessionsthatarealreadyknowntothesystem.

Page 165: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

SummaryInthischapter,youhavehadachancetopracticewhatyouhavelearnedinthepreviouschapterswhilepickingupnewskillsinQt.Sofar,you'llhavegainedaninsightintothearchitectureofQtthatiscommonlyseenandsharedbyitssubmodules.Afterall,networkingandthreadingwilldefinitelybringyourapplicationstoahigherlevel.

Inthenextchapter,besidesparsingXMLandJSONdocuments,we'regoingtorockAndroidwithQt!

Page 166: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

Chapter7.ParsingJSONandXMLDocumentstoUseOnlineAPIsInthischapter,you'llfindthepowerfulapplication,Qt,runningonthepopularAndroiddevices.FollowingtheintroductionofQtapplicationdevelopmentforAndroid,italsoutilizesonlineAPIs,whichusuallyreturnJSONorXMLdocuments.Thetopicsthatarecoveredinthischapterareasfollows:

SettingupQtforAndroidParsingJSONresultsParsingXMLresultsBuildingQtapplicationsforAndroidParsingJSONinQML

SettingupQtforAndroidQtforAndroidrequiresatleastanAPIlevel10(forAndroid2.3.3platforms).MostQtmodulesaresupported,whichmeansyourQtapplicationcanbedeployedonAndroidwithlittleornomodification.Fordevelopment,bothQtWidget-basedapplicationsandQtQuickapplicationsinQtCreatoraresupportedonAndroid.However,settingupQtforAndroidonaWindowsPCisnotverystraightforward.Therefore,beforeweventuredeeperintoanything,let'ssetupthedevelopmentenvironmentforQtonAndroid.

First,youneedtoinstallQtforAndroid.Ifyou'reusinganonlineinstaller,remembertoselecttheAndroidcomponents,asshowninthefollowingscreenshot:

Page 167: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

Here,weonlychoseAndroidarmv7,whichenablesustodeployapplicationsforARMv7Androiddevices.Ifyou'reusinganofflineinstaller,downloadQtfortheAndroidinstaller.

Now,let'sinstallaJavaDevelopmentKit(JDK).ThereisnowaytogetridofJava,sinceAndroidheavilydependsonit.Also,notethatyouneedtoinstallatleastVersion6ofJDK,accordingtohttp://doc.qt.io/qt-5/androidgs.html.YoucandownloadJDKfromhttp://www.oracle.com/technetwork/java/javase/downloads/index.html.YoualsoneedtosetaJAVA_HOMEenvironmentvariableintheJDKinstallationdirectory,D:\ProgramFiles\Java\jdk1.8.0_25.

Now,let'sinstalltwokitsfromGoogle,theAndroidSDKandAndroidNDK.Alwaysremembertodownloadthelatestversion;hereweuseAndroidSDKr24.0.2andAndroidNDKr10b.

AfteryouinstalltheAndroidSDK,runtheSDKManager.InstallorupdateAndroidSDKTools,AndroidSDKPlatform-tools,AndroidSDKBuild-tools,GoogleUSBDriver,atleastoneAPIlevel'sSDKPlatform,andARMEABIv7aSystemImageforthepurposeofourtask.Forthischapter,weinstalledAPI19'sSDKPlatformandARMEABIv7aSystemImage.Then,editthePATHenvironmentvariable.AddthepathoftheplatformandSDKtoolstoitwithasemicolonasaseparator.IfD:\ProgramFiles(x86)\Android\android-sdkisthepathofAndroidSDKTools,itwouldbeasfollows:

D:\ProgramFiles(x86)\Android\android-sdk\platform-tools;D:\ProgramFiles

(x86)\Android\android-sdk\tools

Page 168: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

NoteAndroidSDKandNDKcanbeobtainedontheAndroiddeveloperwebsite,http://developer.android.com.

OnceyoudownloadtheNDK,extractthezipfiletoyourharddrive,D:\android-ndk.Then,addanenvironmentvariablenamedANDROID_NDK_ROOTwiththevalue,D:\android-ndk.

SimilarproceduresshouldbeappliedforApacheAnt.Youcandownloaditfromhttp://ant.apache.org/bindownload.cgi.WeuseApacheAnt1.9.4inthisbook.Thereisnoenvironmentvariablethatneedstobesethere.Now,rebootyourcomputerifyou'reusingWindowssothattheenvironmentvariablescanberefreshedandloadedcorrectly.

OpenAVDManagerandcreateanewvirtualdevice.You'dbetterchooseasmallervirtualdevicesuchasNexusSforthisexercise,asshowninthefollowingscreenshot.Feelfreetochangeitifyouwant,butremembertotickUseHostGPU,whichwillmakethevirtualdeviceuseGLEStoacceleratethegraphics.Ifyouhaven'tturnedthaton,you'llgetanextremelyslowvirtualdevicethatmightevenbetoosluggishtotestapplicationson.

Page 169: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

Now,openQtCreator;navigatetoTools|Options.SeeifQtVersioninBuild&RunhasanAndroidentry.YouhavetomanuallyaddQtforAndroidifit'snotthere.Then,switchtotheAndroidoptions,setupJDK,AndroidSDK,AndroidNDK,andAnt,asshowninthefollowingscreenshot:

Page 170: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

Thewarningformissingarchitecturescanbesafelyignoredbecausewewon'tdevelopapplicationsforMIPSandx86Androidinthischapter.However,payattentiontoitifyouneedtodeployyourapplicationsonthesehardwareplatforms.

ClickonApplyandswitchtotheDevicesoptions.ThereshouldbeaRunonAndroiditemintheDevicecombobox.Anauto-detectedAndroidforarmeabi-v7aisexpectedifyounavigatetoBuild&Run|Kitsnow.

Now,let'stestifwecanrunaQtapplicationonourvirtualAndroiddevice.OpenAVDManagerandstartthevirtualdevice.Westartitfirstbecauseitcouldtakealotoftime.Then,openQtCreatorandmakeasimpleapplication.

1. CreateanewQtWidget-basedapplicationproject.2. SelectAndroidforarmeabi-v7aKit.3. Editmainwindow.uianddragalabeltocentralWidget.4. ChangetheMainWindowpage'slayouttoLayOutVertically(orothers)sothat

thewidgetswillbestretchedautomatically.5. Changethelabel'stexttoHelloAndroid!orsomethingelse.

Waitforthetime-consumingvirtualAndroiddeviceuntilit'sfullystarted.Ifit'snot,clickonRunandwaitforafewminutes.You'llseethisapplicationrunningonourvirtualAndroiddevice.Asseeninthefollowingscreenshot,theQtforAndroiddevelopmentenvironmentissetupsuccessfully.So,wecanmoveonandwriteanapplicationthatcanuseacameratotakephotos:

Page 171: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

TipTestinganapplicationonadesktopwhileit'sincomplete,andthentestingitonamobileplatformwouldsaveplentyoftimecomparedtotestingonthevirtualAndroiddeviceallthetime.Inadditiontothis,it'smuchfastertotestonareal

Page 172: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

devicethanavirtualone.

Insteadoftoleratingaslowemulator,we'regoingtofirstdeveloptheapplicationonadesktop,thendeployitonanactualAndroiddeviceandseeifthereisanythingmismatchedorinappropriateformobiledevices.Makeanyrelevantchangesaccordingly.Thiscouldsaveyouplentyoftime.However,itstilltakesalongertime,eventhoughtheactualAndroiddeviceismuchmoreresponsivethanthevirtualone.

Page 173: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

ParsingJSONresultsTherearetonsofcompaniesthatprovidedevelopersAPIstoaccesstotheirservices,includingthedictionary,weather,andsoon.Inthischapter,we'lluseYahoo!WeatherasanexampletoshowyouhowtouseitsonlineAPItogetweatherdata.FormoredetailsaboutYahoo!WeatherAPI,refertohttps://developer.yahoo.com/weather/.

Now,let'screateanewprojectnamedWeather_Demo,whichisaQtWidget-basedapplicationproject.Asusual,let'sfirstdesigntheUI.

We'veremovedthemenubar,toolbar,andstatusbaraswedidbefore.Then,weaddedaLabel,LineEdit,andPushButtonontopofcentralWidget.TheirobjectnamesarewoeidLabel,woeidEdit,andokButton,respectively.Afterthis,anotherlabelnamedlocationLabelisusedtodisplaythelocationreturnedfromtheAPI.TheredrectangleisHorizontalLayout,whichconsistsoftempLabelandwindLabel,whicharebothLabelandareseparatedbyHorizontalSpacer.AppendLabel,whoseobjectnameisattrLabel,andthenchangeitsalignmenttoAlignRightandAlignBottom.

WhereOnEarthID(WOEID)isa32-bitidentifierthatisuniqueandnonrepetitive.ByusingWOEID,wecanavoidduplicity.However,thisalsomeansthatweneedtofindoutwhatWOEIDisusedforourlocation.Luckily,thereareseveralwebsitesthatprovideyouwitheasy-to-useonlinetoolstogettheWOEID.OneofthemistheZourbuthproject,Yahoo!WOEIDLookup,whichcanbeaccessedathttp://zourbuth.com/tools/woeid/.

Now,let'smoveonandfocusontheparsingofAPIresults.WecreatedanewC++

Page 174: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

class,Weather,todealwiththeYahoo!WeatherAPI.I'dliketointroduceyoutoparsingtheJSON(JavaScriptObjectNotation)resultsbeforeXML.However,beforewecooktheWeatherclass,remembertoaddnetworktoQTintheprojectfile.Inthiscase,theWeather_Demo.proprojectfilelookslikethis:

QT+=coreguinetwork

greaterThan(QT_MAJOR_VERSION,4):QT+=widgets

TARGET=Weather_Demo

TEMPLATE=app

SOURCES+=main.cpp\

mainwindow.cpp\

weather.cpp

HEADERS+=mainwindow.h\

weather.h

FORMS+=mainwindow.ui

Now,wecanwritetheWeatherclass.Itsweather.hheaderfileispastedasfollows:

#ifndefWEATHER_H

#defineWEATHER_H

#include<QObject>

#include<QJsonDocument>

#include<QJsonObject>

#include<QNetworkAccessManager>

#include<QNetworkReply>

#include<QImage>

classWeather:publicQObject

{

Q_OBJECT

public:

explicitWeather(QObject*parent=0);

signals:

voidupdateFinished(constQString&location,constQString

&temp,constQString&wind);

voidimageDownloaded(constQImage&);

publicslots:

voidupdateData(constQString&woeid);

voidgetAttrImg();

private:

QNetworkAccessManager*naManager;

QNetworkReply*imgReply;

QImageattrImg;

Page 175: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

privateslots:

voidonSSLErrors(QNetworkReply*);

voidonQueryFinished(QNetworkReply*);

};

#endif//WEATHER_H

Inadditiontotheweatherinformationquery,wealsousethisclasstogetanattributionimage,whichisstatedintheYahoo!documentation.ItiskindoftrivialintraditionalQt/C++thatwehavetouseQNetworkAccessManagertoaccessQUrl,becauseQJsonDocumentcannotloadfromQUrldirectly.Anyway,let'sseehowwegettheresultfromtheYahoo!WeatherAPIintheweather.cppfile.Theheaderpartincludesthefollowinglines:

#include<QDebug>

#include<QNetworkRequest>

#include<QJsonArray>

#include"weather.h"

Then,let'sseetheconstructorofWeather.Here,wesimplyconstructtheQNetworkAccessManagerobject,naManager,andconnectitssignals:

Weather::Weather(QObject*parent):

QObject(parent)

{

naManager=newQNetworkAccessManager(this);

connect(naManager,&QNetworkAccessManager::finished,this,

&Weather::onQueryFinished);

connect(naManager,&QNetworkAccessManager::sslErrors,

this,&Weather::onSSLErrors);

}

TheonSSLErrorsslotissimplytolettheQNetworkReplyobjectignorealltheSSLerrors.Thiswon'tcauseanyseriousproblemsinthiscase.However,ifyou'redealingwithasecurecommunicationoranythingelsethatneedstovalidatetheconnection,youmaywishtolookintotheerror.

voidWeather::onSSLErrors(QNetworkReply*re)

{

re->ignoreSslErrors();

}

Then,let'schecktheupdateDatafunctionbeforeonQueryFinished.Here,weconstructQUrl,whichistheYahoo!WeatherAPI'sexactaddress.Notethatyoudon'tneedtouseanHTMLcodeforQUrl.Infact,it'dbebettertouseaspacealongwith

Page 176: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

theothersymbolsdirectly.Afterthis,similartothepreviouschapter,weuseQNetworkRequesttowrapthisQUrlanddispatchtherequestthroughQNetworkAccessManager.

voidWeather::updateData(constQString&woeid)

{

QUrlurl("https://query.yahooapis.com/v1/public/yql?

q=select*fromweather.forecastwherewoeid="+woeid+

"&format=json");

QNetworkRequestreq(url);

naManager->get(req);

}

AsforthegetAttrImgfunction,it'salmostthesame.Theonlydifferenceisthatthisfunctionisusedtogetanattributionimageinsteadofweatherinformation.WestorethereplyasimgReplysothatwecandistinguishtheimagefromtheweather.

voidWeather::getAttrImg()

{

QUrlurl("https://poweredby.yahoo.com/purple.png");

QNetworkRequestreq(url);

imgReply=naManager->get(req);

}

IfthecorrespondingQNetworkReplyobjectisfinished,theonQueryFinishedslotfunctionwillbeexecuted,whichisshowninthefollowingcode.Afterallthepavement,let'sseewhat'sinsidethisfunction.Wecancheckwhetherthereisanyerrorinthereplyattheverybeginning.Then,ifit'simgReply,wecookQImagefromthedataandemitasignaltosendthisimageout.Ifnoneofthesehappen,we'llparsetheweatherfromtheJSONreply.

voidWeather::onQueryFinished(QNetworkReply*re)

{

if(re->error()!=QNetworkReply::NoError){

qDebug()<<re->errorString();

re->deleteLater();

return;

}

if(re==imgReply){

attrImg=QImage::fromData(imgReply->readAll());

emitimageDownloaded(attrImg);

imgReply->deleteLater();

return;

}

QByteArrayresult=re->readAll();

re->deleteLater();

Page 177: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

QJsonParseErrorerr;

QJsonDocumentdoc=QJsonDocument::fromJson(result,&err);

if(err.error!=QJsonParseError::NoError){

qDebug()<<err.errorString();

return;

}

QJsonObjectobj=doc.object();

QJsonObjectres=

obj.value("query").toObject().value("results").toObject().valu

e("channel").toObject();

QJsonObjectlocObj=res["location"].toObject();

QStringlocation;

for(QJsonObject::ConstIteratorit=locObj.constBegin();

it!=locObj.constEnd();++it){

location.append((*it).toString());

if((it+1)!=locObj.constEnd()){

location.append(",");

}

}

QStringtemperature=res["item"].toObject()

["condition"].toObject()["temp"].toString()+

res["units"].toObject()["temperature"].toString();

QJsonObjectwindObj=res["wind"].toObject();

QStringwind;

for(QJsonObject::ConstIteratorit=windObj.constBegin();

it!=windObj.constEnd();++it){

wind.append(it.key());

wind.append(":");

wind.append((*it).toString());

wind.append("\n");

}

emitupdateFinished(location,temperature,wind);

}

AsImentionedbefore,itistrivial.First,wereadtheresultfromQNetworkReply,andthenuseQJsonDocument::fromJsontoparsethebytearrayasaJSONdocument.Ifthereisanerrorduringtheprocess,wesimplyprinttheerrorstringandreturn.Then,weneedtogetQJsonObjectcontainedinQJsonDocument.Onlythencanweparsealltheinformationinsideit.Theformattedresultusing560743astheWOEIDisshownasfollows:

{

"query":{

"count":1,

"created":"2014-12-05T23:19:54Z",

"lang":"en-GB",

"results":{

"channel":{

Page 178: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

"title":"Yahoo!Weather-Dublin,IE",

"link":"http://us.rd.yahoo.com/dailynews/rss/weather/Dublin__I

E/*http://weather.yahoo.com/forecast/EIXX0014_f.html",

"description":"Yahoo!WeatherforDublin,IE",

"language":"en-us",

"lastBuildDate":"Fri,05Dec20149:59pmGMT",

"ttl":"60",

"location":{

"city":"Dublin",

"country":"Ireland",

"region":"DUB"

},

"units":{

"distance":"mi",

"pressure":"in",

"speed":"mph",

"temperature":"F"

},

"wind":{

"chill":"29",

"direction":"230",

"speed":"8"

},

"atmosphere":{

"humidity":"93",

"pressure":"30.36",

"rising":"1",

"visibility":"6.21"

},

"astronomy":{

"sunrise":"8:22am",

"sunset":"4:09pm"

},

"image":{

"title":"Yahoo!Weather",

"width":"142",

"height":"18",

"link":"http://weather.yahoo.com",

"url":"http://l.yimg.com/a/i/brand/purplelogo//uh/us/news-

wea.gif"

},

"item":{

"title":"ConditionsforDublin,IEat9:59pmGMT",

"lat":"53.33",

"long":"-6.29",

"link":"http://us.rd.yahoo.com/dailynews/rss/weather/Dublin__I

E/*http://weather.yahoo.com/forecast/EIXX0014_f.html",

"pubDate":"Fri,05Dec20149:59pmGMT",

"condition":{

"code":"29",

"date":"Fri,05Dec20149:59pmGMT",

"temp":"36",

Page 179: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

"text":"PartlyCloudy"

},

"description":"\n<img

src=\"http://l.yimg.com/a/i/us/we/52/29.gif\"/><br

/>\n<b>CurrentConditions:</b><br/>\nPartlyCloudy,36F<BR

/>\n<BR/><b>Forecast:</b><BR/>\nFri-PartlyCloudy.High:

44Low:39<br/>\nSat-MostlyCloudy.High:48Low:41<br

/>\nSun-MostlySunny/Wind.High:43Low:37<br/>\nMon-

MostlySunny/Wind.High:43Low:37<br/>\nTue-PMLight

Rain/Wind.High:52Low:38<br/>\n<br/>\n<a

href=\"http://us.rd.yahoo.com/dailynews/rss/weather/Dublin__IE

/*http://weather.yahoo.com/forecast/EIXX0014_f.html\">Full

ForecastatYahoo!Weather</a><BR/><BR/>\n(providedby<a

href=\"http://www.weather.com\">TheWeatherChannel</a>)

<br/>\n",

"forecast":[

{

"code":"29",

"date":"5Dec2014",

"day":"Fri",

"high":"44",

"low":"39",

"text":"PartlyCloudy"

},

{

"code":"28",

"date":"6Dec2014",

"day":"Sat",

"high":"48",

"low":"41",

"text":"MostlyCloudy"

},

{

"code":"24",

"date":"7Dec2014",

"day":"Sun",

"high":"43",

"low":"37",

"text":"MostlySunny/Wind"

},

{

"code":"24",

"date":"8Dec2014",

"day":"Mon",

"high":"43",

"low":"37",

"text":"MostlySunny/Wind"

},

{

"code":"11",

"date":"9Dec2014",

"day":"Tue",

"high":"52",

"low":"38",

"text":"PMLightRain/Wind"

Page 180: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

}

],

"guid":{

"isPermaLink":"false",

"content":"EIXX0014_2014_12_09_7_00_GMT"

}

}

}

}

}

}

NoteFordetailsaboutJSON,visithttp://www.json.org.

Asyoucansee,alltheinformationisstoredinsidequery/results/channel.Therefore,weneedtoconvertittoQJsonObject,levelbylevel.Asyoucanseeinthecode,QJsonObjectresischannel.NotethatthevaluefunctionwillreturnaQJsonValueobjectandyouwillneedtocalltoObject()tomakeitQJsonObjectbeforeyoucanusethevaluefunctiontoparsethevalueagain.Afterthis,it'sprettystraightforward.ThelocObjobjectisthelocationwhereweuseaforlooptoputthevaluestogether,whereasQJsonObject::ConstIteratorisjustQt'swrapperofSTLconst_iterator.

Toobtainthecurrenttemperature,weneedtogothroughasimilarjourneytochannelbecausethetemperatureisinitem/condition/temp,whileitsunitisunits/temperature.

Asforthewindsection,weusealazywaytoretrievethedata.ThewindObjlineisnotasinglevaluestatement;instead,ithasseveralkeysandvalues.Therefore,weuseaforlooptowalkthroughthisarrayandretrievebothofitskeysalongwithitsvalue,andsimplyputthemtogether.

Now,let'sgobacktotheMainWindowclasstoseehowtointeractwiththeWeatherclass.TheheaderfileofMainWindow,whichismainwindow.h,ispastedhere:

#ifndefMAINWINDOW_H

#defineMAINWINDOW_H

#include<QMainWindow>

#include"weather.h"

namespaceUi{

classMainWindow;

}

Page 181: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

classMainWindow:publicQMainWindow

{

Q_OBJECT

public:

explicitMainWindow(QWidget*parent=0);

~MainWindow();

private:

Ui::MainWindow*ui;

Weather*w;

privateslots:

voidonOkButtonClicked();

voidonAttrImageDownloaded(constQImage&);

voidonWeatherUpdateFinished(constQString&location,const

QString&temp,constQString&wind);

};

#endif//MAINWINDOW_H

WedeclareaWeatherobjectpointer,w,astheMainWindowclass'sprivatemember.Meanwhile,onOkButtonClickedisthehandlerwhenokButtongetsclicked.TheonAttrImageDownloadedandonWeatherUpdateFinishedfunctionswillbecoupledwiththeWeatherclass'ssignals.Now,let'sseewhat'sinsidethesourcefile:

#include"mainwindow.h"

#include"ui_mainwindow.h"

MainWindow::MainWindow(QWidget*parent):

QMainWindow(parent),

ui(newUi::MainWindow)

{

ui->setupUi(this);

w=newWeather(this);

connect(ui->okButton,&QPushButton::clicked,this,

&MainWindow::onOkButtonClicked);

connect(w,&Weather::updateFinished,this,

&MainWindow::onWeatherUpdateFinished);

connect(w,&Weather::imageDownloaded,this,

&MainWindow::onAttrImageDownloaded);

w->getAttrImg();

}

MainWindow::~MainWindow()

{

deleteui;

}

voidMainWindow::onOkButtonClicked()

{

Page 182: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

w->updateData(ui->woeidEdit->text());

}

voidMainWindow::onAttrImageDownloaded(constQImage&img)

{

ui->attrLabel->setPixmap(QPixmap::fromImage(img));

}

voidMainWindow::onWeatherUpdateFinished(constQString

&location,constQString&temp,constQString&wind)

{

ui->locationLabel->setText(location);

ui->tempLabel->setText(temp);

ui->windLabel->setText(wind);

}

Intheconstructor,apartfromthesignalsconnectionandthewobject'sconstruction,wecallgetAttrImgofwtoretrievetheattributionimage.Whentheimageisdownloaded,theonAttrImageDownloadedslotfunctionwillbeexecutedwheretheimagewillbedisplayedonattrLabel.

OncetheuserclicksonokButton,theonOkButtonClickedslotfunctiongetsexecuted,wherewecalltheupdateDatafunctionoftheWeatherclasstopasstheWOEID.Then,whentheupdateisfinished,theupdateFinishedsignalisemittedandonWeatherUpdateFinishedisexecuted.WejustusethesethreeQStringobjectstosetthecorrespondinglabel'stext.

Now,testyourapplicationtoseeifit'srunningasshowninthisscreenshot:

Page 183: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

ParsingXMLresultsAlthoughalotofAPIsprovidebothXMLandJSONresults,youmaystillfindthatsomeofthemonlyofferoneformat.Besides,youmightfeelthatparsingJSONinC++/Qtisnotapleasantprocess.YoumayrememberhoweasyitistoparsetheXMLmodelinQML/QtQuick.Well,let'sseehowtodothisinC++/Qt.

Tomakeuseofanxmlmodule,wehavetoaddxmltoQTintheprojectfile,thesamewaywedidtonetwork.Thistime,QthasprovidedanXMLreaderclasscalledQXmlStreamReadertohelpusparsetheXMLdocuments.ThefirstthingweneedtodoistochangetheupdateDatafunctionintheWeatherclasstolettheYahoo!WeatherAPIreturnanXMLresult.

voidWeather::updateData(constQString&woeid)

{

QUrlurl("https://query.yahooapis.com/v1/public/yql?q=select

*fromweather.forecastwherewoeid="+woeid+

"&format=xml");

QNetworkRequestreq(url);

naManager->get(req);

}

Thechangingof&format=jsonto&format=xmlneedstobedonehere.Incontrasttothis,thereisalotofworktodointheonQueryFinishedslotfunction.TheoldJSONpartiscommentedoutsothatwecanwritetheXMLparsingcode.Themodifiedfunctionwithoutthecommentisshownasfollows:

voidWeather::onQueryFinished(QNetworkReply*re)

{

if(re->error()!=QNetworkReply::NoError){

qDebug()<<re->errorString();

re->deleteLater();

return;

}

if(re==imgReply){

attrImg=QImage::fromData(imgReply->readAll());

emitimageDownloaded(attrImg);

imgReply->deleteLater();

return;

}

QByteArrayresult=re->readAll();

re->deleteLater();

QXmlStreamReaderxmlReader(result);

while(!xmlReader.atEnd()&&!xmlReader.hasError()){

QXmlStreamReader::TokenTypetoken=xmlReader.readNext();

Page 184: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

if(token==QXmlStreamReader::StartElement){

QStringRefname=xmlReader.name();

if(name=="channel"){

parseXMLChannel(xmlReader);

}

}

}

}

Here,parseXMLChannelisanewlycreatedmemberfunction.Wecanuseaseparatefunctiontomakeourcodeneatandtidy.

NoteRemembertodeclaretheparseXMLChannelfunctionintheheaderfile.

Itsdefinitionispastedasfollows:

voidWeather::parseXMLChannel(QXmlStreamReader&xml)

{

QStringlocation,temperature,wind;

QXmlStreamReader::TokenTypetoken=xml.readNext();

while(token!=QXmlStreamReader::EndDocument){

if(token==QXmlStreamReader::EndElement||

xml.name().isEmpty()){

token=xml.readNext();

continue;

}

QStringRefname=xml.name();

if(name=="location"){

QXmlStreamAttributeslocAttr=xml.attributes();

location=locAttr.value("city").toString()+","+

locAttr.value("country").toString()+","+

locAttr.value("region").toString();

}

elseif(name=="units"){

temperature=

xml.attributes().value("temperature").toString();

}

elseif(name=="wind"){

QXmlStreamAttributeswindAttr=xml.attributes();

for(QXmlStreamAttributes::ConstIteratorit=

windAttr.begin();it!=windAttr.end();++it){

wind.append(it->name().toString());

wind.append(":");

wind.append(it->value());

wind.append("\n");

}

}

Page 185: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

elseif(name=="condition"){

temperature.prepend(xml.attributes().value("temp").toString())

;

break;//wegotallinformation,exittheloop

}

token=xml.readNext();

}

emitupdateFinished(location,temperature,wind);

}

BeforewewalkthroughparseXMLChannelfunction,I'dliketoshowyouwhattheXMLdocumentlookslike,shownasfollows:

<?xmlversion="1.0"?>

<queryxmlns:yahoo="http://www.yahooapis.com/v1/base.rng"

yahoo:count="1"yahoo:created="2014-12-06T22:50:22Z"

yahoo:lang="en-GB">

<results>

<channel>

<title>Yahoo!Weather-Dublin,IE</title>

<link>http://us.rd.yahoo.com/dailynews/rss/weather/Dublin__IE/

*http://weather.yahoo.com/forecast/EIXX0014_f.html</link>

<description>Yahoo!WeatherforDublin,IE</description>

<language>en-us</language>

<lastBuildDate>Sat,06Dec20149:59pm

GMT</lastBuildDate>

<ttl>60</ttl>

<yweather:location

xmlns:yweather="http://xml.weather.yahoo.com/ns/rss/1.0"

city="Dublin"country="Ireland"region="DUB"/>

<yweather:units

xmlns:yweather="http://xml.weather.yahoo.com/ns/rss/1.0"

distance="mi"pressure="in"speed="mph"temperature="F"/>

<yweather:wind

xmlns:yweather="http://xml.weather.yahoo.com/ns/rss/1.0"

chill="41"direction="230"speed="22"/>

<yweather:atmosphere

xmlns:yweather="http://xml.weather.yahoo.com/ns/rss/1.0"

humidity="93"pressure="30.03"rising="2"visibility="6.21"/>

<yweather:astronomy

xmlns:yweather="http://xml.weather.yahoo.com/ns/rss/1.0"

sunrise="8:24am"sunset="4:07pm"/>

<image>

<title>Yahoo!Weather</title>

<width>142</width>

<height>18</height>

<link>http://weather.yahoo.com</link>

<url>http://l.yimg.com/a/i/brand/purplelogo//uh/us/news-

wea.gif</url>

Page 186: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

</image>

<item>

<title>ConditionsforDublin,IEat9:59pm

GMT</title>

<geo:lat

xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#">53.33</ge

o:lat>

<geo:long

xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#">-6.29</ge

o:long>

<link>http://us.rd.yahoo.com/dailynews/rss/weather/Dublin__IE/

*http://weather.yahoo.com/forecast/EIXX0014_f.html</link>

<pubDate>Sat,06Dec20149:59pmGMT</pubDate>

<yweather:condition

xmlns:yweather="http://xml.weather.yahoo.com/ns/rss/1.0"

code="27"date="Sat,06Dec20149:59pmGMT"temp="48"

text="MostlyCloudy"/>

<description><![CDATA[<img

src="http://l.yimg.com/a/i/us/we/52/27.gif"/><br/><b>Current

Conditions:</b><br/>MostlyCloudy,48F<BR/><BR/>

<b>Forecast:</b><BR/>Sat-LightRain/WindLate.High:48

Low:42<br/>Sun-MostlySunny/Wind.High:44Low:37<br/>

Mon-Sunny.High:43Low:37<br/>Tue-Showers/Wind.High:

53Low:39<br/>Wed-PartlyCloudy/Wind.High:45Low:39<br

/><br/><a

href="http://us.rd.yahoo.com/dailynews/rss/weather/Dublin__IE/

*http://weather.yahoo.com/forecast/EIXX0014_f.html">Full

ForecastatYahoo!Weather</a><BR/><BR/>(providedby<a

href="http://www.weather.com">TheWeatherChannel</a>)

<br/>]]></description>

<yweather:forecast

xmlns:yweather="http://xml.weather.yahoo.com/ns/rss/1.0"

code="11"date="6Dec2014"day="Sat"high="48"low="42"

text="LightRain/WindLate"/>

<yweather:forecast

xmlns:yweather="http://xml.weather.yahoo.com/ns/rss/1.0"

code="24"date="7Dec2014"day="Sun"high="44"low="37"

text="MostlySunny/Wind"/>

<yweather:forecast

xmlns:yweather="http://xml.weather.yahoo.com/ns/rss/1.0"

code="32"date="8Dec2014"day="Mon"high="43"low="37"

text="Sunny"/>

<yweather:forecast

xmlns:yweather="http://xml.weather.yahoo.com/ns/rss/1.0"

code="11"date="9Dec2014"day="Tue"high="53"low="39"

text="Showers/Wind"/>

<yweather:forecast

xmlns:yweather="http://xml.weather.yahoo.com/ns/rss/1.0"

code="24"date="10Dec2014"day="Wed"high="45"low="39"

text="PartlyCloudy/Wind"/>

<guid

isPermaLink="false">EIXX0014_2014_12_10_7_00_GMT</guid>

</item>

</channel>

Page 187: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

</results>

</query>

<!--total:27-->

<!--engine4.yql.bf1.yahoo.com-->

Asyoucandeduce,theXMLstructuresharesalotofsimilaritieswiththeJSONdocument.Forinstance,allthedataweneedisstillstoredinquery/results/channel.Thedifferenceis,however,moresignificantthanyoumayhaveexpected.

NoteIfyouwanttolearnXMLthoroughly,checktheXMLtutorialathttp://www.w3schools.com/xml/.

IntheonQueryFinishedslot,weuseawhilelooptoletxmlReaderkeepreadinguntiltheendoruntilanerror.ThereadNextfunctionoftheQXmlStreamReaderclasswillreadthenexttokenandreturnitstype.TokenTypeisanenum,whichdescribesthetypeoftokencurrentlybeingread.EachtimeyoucallreadNext,QXmlStreamReaderwillmoveforwardbyonetoken.Ifwewanttoreadallthedataofoneelement,wemayhavetoreaditfromthebeginning.Therefore,weuseanifstatementtoensurethatthetokenisatthestarting.Inadditiontothis,wetestifwe'rereadingthechannelnow.Then,wecallparseXMLChanneltoretrievealldatathatweneed.

IntheparseXMLChannelfunction,prettymuchthesamestrategyisused.Wetestthenameelementsothatweknowwhichstagewearein.Onethingworthyourattentionisthatallprefixessuchasyweather:areomitted.Hence,youshoulduselocationinsteadofyweather:location.OtherpartsaresimilartotheircounterpartsinJSON,whereQStringRefissimilartoQJsonValue.Lastbutnotleast,QXmlStreamReaderisastreamreader,whichmeansthatitreadsinorder.Inotherwords,wecanbreakthewhileloopafterwegettempinconditionsinceconditionisthelastelementthatwe'reinterestedin.

Afterthesechanges,youcanbuildandrunthisapplicationagainandyoushouldexpectittoruninthesamemanner.

Page 188: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

BuildingQtapplicationsforAndroidYoumaywonderhowtobuildQtapplicationsforAndroiddevicessincethisapplicationisbuiltfordesktopPCs.Well,it'smucheasierthanyouthought.

1. SwitchtoProjectsmode.2. ClickonAddKitandselectAndroidforarmeabit-v7a(GCC4.9andQt5.3.2).

Notethatthetextmaydifferalittlebit.3. Pluginyourphoneifyou'reusingitasthetargetAndroiddevice.4. OpenCommandPromptandrunadbdevices.Makesureyourdeviceisonthe

list.

Now,clickonRunandQtwillpromptadialogaskingyoutoselecttheAndroiddevice,asshowninthefollowingscreenshot:

WechoosetorunourapplicationonanactualAndroiddevice,whichisanHTCOnephoneinthiscase.Ifyoudon'thaveanyavailableAndroiddevices,youmayhavetocreateavirtualdevice,asmentionedatthebeginningofthischapter.Forboththeoptions,choosethedeviceandclickontheOKbutton.

Page 189: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

NoteOnanactualAndroiddevice,youneedtogotoSettingsandturnonUSBdebugginginDeveloperoptions.

Asyoucanseefromthefollowingscreenshot,thedemonstrationrunswell.ItdefinitelyneedsongoingimprovementsandUIoptimizationbeforesubmitting,though.However,rememberthatwedesignedandbuiltthisapplicationforadesktopPC!Wehavejustbuiltitforamobilephonewithoutanymodificationanditrunsasexpected.

Page 190: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount
Page 191: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

Whenyoutesttheapplication,alltheinformationisprintedtotheApplicationOutputpanelinQtCreator.Thiscouldbeusefulwhenyourapplicationrunsunexpectedly.

Page 192: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

ParsingJSONinQMLLet'srewritetheweatherdemoinQML.YouwillfindouthoweasyandelegantitistowritesuchanapplicationinQML.SincetheXMLpartisalreadycoveredinthepreviouschapter,we'llfocusonparsingJSONthistime.

First,createanewQtQuickapplicationprojectnamedWeather_QML.Keeptheothersettingsasdefault,whichmeansweuseQtQuickControls.RemembertotickthecheckboxoftheAndroidkit.

CreateanewQMLfilenamedWeather.qmltomimictheWeatherclassinthepreviousC++code.Thisfileispastedhere:

importQtQuick2.3

importQtQuick.Controls1.2

Rectangle{

Column{

anchors.fill:parent

spacing:6

Label{

id:location

width:parent.width

fontSizeMode:Text.Fit

minimumPointSize:9

font.pointSize:12

}

Row{

spacing:20

width:parent.width

height:parent.height

Label{

id:temp

width:parent.width/2

height:parent.height

fontSizeMode:Text.Fit

minimumPointSize:12

font.pointSize:72

font.bold:true

}

Label{

id:wind

width:temp.width-20

height:parent.height

fontSizeMode:Text.Fit

minimumPointSize:9

Page 193: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

font.pointSize:24

}

}

}

Image{

id:attrImg

anchors{right:parent.right;bottom:parent.bottom}

fillMode:Image.PreserveAspectFit

source:'https://poweredby.yahoo.com/purple.png'

}

functionquery(woeid){

varurl='https://query.yahooapis.com/v1/public/yql?

q=select*fromweather.forecastwherewoeid='+woeid+

'&format=json'

varres

vardoc=newXMLHttpRequest()

doc.onreadystatechange=function(){

if(doc.readyState==XMLHttpRequest.DONE){

res=doc.responseText

parseJSON(res)

}

}

doc.open('GET',url,true)

doc.send()

}

functionparseJSON(data){

varobj=JSON.parse(data)

if(typeof(obj)=='object'){

if(obj.hasOwnProperty('query')){

varch=obj.query.results.channel

varloc='',win=''

for(varlkinch.location){

loc+=ch.location[lk]+','

}

for(varwkinch.wind){

win+=wk+':'+ch.wind[wk]+'\n'

}

location.text=loc

temp.text=ch.item.condition.temp+

ch.units.temperature

wind.text=win

}

}

}

}

ThefirstpartisjustaQMLversionUIofthepreviousapplication.YoumaywanttopayattentiontothefontSizeModeandminimumPointSizepropertyinLabel.ThesepropertiesarenewlyintroducedinQt5,andenablethetextscaletobedynamically

Page 194: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

adjusted.BysettingText.FitasfontSizeMode,it'llshrinkthetextifheightorwidthisnotsufficientforthetext,whereminimumPointSizeistheminimumpointsize.Thetextwillgetelidedifitcan'tdisplayataminimumsize.Similartotheelideproperty,youhavetoexplicitlysetthewidthandheightpropertyofTextorLabeltomakethisdynamicmechanismwork.

TheattributionimageisdisplayedinaslightlydifferentwayfromC++.WeutilizetheflexibilityofQtQuicktofloatImageontopofthewholeitembysettingonlyanchors.Inadditiontothis,wedon'tneedtouseQNetworkAccessManagertodownloadtheimage.It'sallinone.

AftertheUIpart,wecreatethetwoJavaScriptfunctionstodothedirtywork.ThequeryfunctionisusedtosendanhttprequestandpassthereceiveddatatotheparseJSONfunctiononceit'sdone.Don'tgetconfusedbyXMLinXMLHttpRequest;it'sjustatraditionalnamingconvention.Then,wecreateahandlerfunctionforonreadystatechanged,whichistocallparseJSONwhentherequestisdone.Notethattheopenfunctionwon'tsendtherequest,onlythesendfunctiondoes.

It'sstillshortandcleanintheparseJSONfunction.JSON.parsewillreturnaJSONobjectifitisparsedsuccessfully.Therefore,weneedtotestwhetheritstypeisobjectbeforewegetintoparsing.Then,wejustdoonemoretesttoseewhetherithasqueryasitsproperty.Ifso,wecanstartextractingdatafromobj.UnlikeitsC++counterpart,wecantreatallitskeysasitspropertiesandusethedotoperationtoaccessthemdirectly.Toshortentheoperations,wefirstcreateachvariable,whichisquery/results/channel.Next,weextractthedatafromthechobject.Finally,wechangethetextdirectly.

NoteThech.locationandch.windobjectscanbetreatedasQVariantMapobjects.Thus,wecanusetheforlooptoeasilyextractthevalues.

Let'seditthemain.qmlfileasshownhere:

importQtQuick2.3

importQtQuick.Controls1.2

import"qrc:/"

ApplicationWindow{

visible:true

width:240

height:320

title:qsTr("WeatherQML")

Page 195: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

Row{

id:inputField

anchors{top:parent.top;topMargin:10;left:

parent.left;leftMargin:10;right:parent.right;rightMargin:

10}

spacing:6

Label{

id:woeidLabel

text:"WOEID"

}

TextField{

width:inputField.width-woeidLabel.width

inputMethodHints:Qt.ImhDigitsOnly

onAccepted:weather.query(text)

}

}

Weather{

anchors{top:inputField.bottom;topMargin:10;left:

parent.left;leftMargin:10;right:parent.right;rightMargin:

10;bottom:parent.bottom;bottomMargin:10}

id:weather

}

}

RowisthesameWOEIDinputpanel,forwhichwedon'tcreateanOKbuttonthistime.Instead,wehandletheacceptedsignalinonAcceptedbycallingthequeryfunctioninweather,whichisaWeatherelement.WesettheinputMethodHintspropertytoQt.ImhDigitsOnly,whichisusefulonmobileplatforms.ThisapplicationshouldrunalmostthesameastheC++oneorshouldwesaybetter.

Page 196: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

TheinputMethodHintspropertymayseemuselessonadesktop;indeed,youneedtouseinputMaskandvalidatortorestricttheacceptableinput.However,itshowsitspoweronmobiles,asfollows:

Page 197: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount
Page 198: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

Asyoucansee,inputMethodHintsnotonlyrestrictstheinput,butitalsoprovidesabetterexperienceforusers.ThisisalsoviableinaC++/Qtdevelopment;youcanfindtherelevantfunctionstoachievethis.ThewholepointinQMListhatparsingtheJSONandXMLdocumentsiseasierandtidierthanC++.

Page 199: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

SummaryAfterthischapter,you'reexpectedtohandlecommontasksandwritetypesofreal-worldapplications.You'llgetyourownunderstandingofQtQuickandtraditionalQt.It'salsoacurrenttrendtowritehybridapplications,whichmakefulluseofbothofthembywritingtheC++pluginstoenhanceQML.QMLhasanunbeatableadvantageofflexibleUIdesign,whichisevenmoreobviousonmobileplatforms.Whilethedevelopmentpartisnearingtheend,inthenextchapterwe'lltalkabouthowtosupportmultiplelanguages.

Page 200: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

Chapter8.EnablingYourQtApplicationtoSupportOtherLanguagesInthiseraofglobalization,theinternationalizationandlocalizationofapplicationsisalmostinevitable.Fortunately,Qtprovidesrelevantclasses,alongwithsomehandytoolssuchasQtLinguisttoeasetheburdenofdevelopersandtranslators.Inthischapter,wewillusetwoexampleapplicationstodemonstratethefollowingtopics:

InternationalizationofQtapplicationsTranslatingQtWidgetsapplicationsDisambiguatingidenticaltextsChanginglanguagesdynamicallyTranslatingQtQuickapplications

InternationalizationofQtapplicationsInternationalizationandlocalizationaretheprocessesofadaptingtheapplicationtootherlocales,whichmightincludedifferentlanguagesandregionaldifferences.Insoftwaredevelopment,internationalizationreferstodesigninganapplicationinsuchawaythatitcanbeadaptedtovariouslanguagesandregionswithoutcodechanges.Ontheotherhand,localizationmeansadaptinginternationalizedsoftwareforaspecificlanguageorregion.Thisusuallyinvolveslocale-specificcomponentsandtranslatingtext.

Qthasdonealottofreedevelopersfromdifferentwritingsystems.Wedon'tneedtoworryabouthowdifferentlanguagesdisplayandinput,aslongasweuseQt'sinputanddisplaycontrolsortheirsubclasses.

Inmostcases,whatweneedtodoistoproducetranslationsandenablethemintheapplication.QtofferstheQTranslatorclass,whichloadsthetranslationfileanddisplaysthecorrespondinglanguageonthescreen.Theprocedureisconcludedinthefollowingdiagram:

Page 201: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

Firstofall,Qtwon'tjustmakeallthestringstranslatable,becausethatwouldobviouslybeadisaster.Instead,youneedtoexplicitlysetwhetherthestringistranslatableincodeorintheDesignmode.IntheQt/C++code,usethetr()functiontoencloseallthestringsthatcanbetranslated.WeusetheqsTr()functiontodothisjobintheQtQuick/QMLcode.Letmeshowyouanexample.Hereisademonstrationofthenormalusageofastring:

qDebug()<<"HelloWorld";

ThiswilloutputHelloWorldtothestandardoutputstream,whichisyourcommandpromptorshellingeneralcases.IfwewanttomakeHelloWorldtranslatable,weneedtouseatr()functiontoenclosethestring,asfollows:

qDebug()<<tr("HelloWorld");

Sincetr()isastaticpublicmemberfunctionoftheQObjectclass,youcanstilluseitevenforanonQObjectclass.

Page 202: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

qDebug()<<QObject::tr("HelloWorld");

Then,weneedtousethelupdatecommand,whichislocatedinTools|External|Linguist|UpdateTranslations(lupdate)inQtCreator.Thiswillupdate,orcreateifthetranslationsource(TS)filedoesn'texist.YoucanthenuseQtLinguisttotranslatethestrings.Beforeyoureleaseyourapplication,runthelreleasecommand,whichislocatedinTools|External|Linguist|ReleaseTranslations(lrelease),togeneratetheQtmessage(QM)filesthatcanbeloadedbyanapplicationdynamically.Don'tworryifitconfusesyou;we'llusetwoexamplestowalkyouthroughtheseprocedures.

Page 203: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

TranslatingQtWidgetsapplicationsFirst,let'screateanewQtWidgetproject,whosenameisInternationalization.Then,editmainwindow.uiintheDesignmode.

1. Asusual,removethestatusbar,menubar,andtoolbar.2. AddLabelintocentralWidgetandchangeitsobjectnametononTransLabel.

Then,changeitstexttoThisisanon-translatablelabelandunchecktranslatableundertextinPropertyEditor.

3. DragaPushButtonjustbeneathnonTransLabelwithtransButtonasitsobjectname.ChangeitstexttoThisisatranslatablebutton.

4. ChangeLayouttoLayOutVerticallyinMainWindow.5. Resizetheframetoacomfortablesize.

GobacktoeditingtheInternationalization.proprojectfileintheEditmode.Addalineindicatingthetranslationsourcefile,whichisshownasfollows:

TRANSLATIONS=Internationalization_de.ts

The_desuffixisalocalecode,indicatingthatthisisaGermantranslationsourcefile.ThelocalecodesaredefinedbyInternetEngineeringTaskForceintheBCP47documentseries.Historically,QtfollowsthePOSIXdefinition,whichisslightlydifferentfromBCP47.Inthis,itusesunderscores(_)insteadofhyphens(-)toseparatesubtags.Inotherwords,BrazilianPortugueseisexpressedaspt_BRinsteadofpt-BR.Meanwhile,QthasprovidedsomeAPIstoconformthelocalenametoaBCP47definitionsincetheQt4.8version.

Toensurethischangeisvalid,savetheprojectfileandright-clickontheprojectandselectRunqmake.Afterthis,wecangeneratethetranslationsourcefile,whichisexactlyInternationalization_de.ts,byexecutingthelupdatecommand.TheresultswillbeprintedintheGeneralMessagespanel,whichcontainsthestringsaddedtotheTSfile,asshownhere:

Updating'Internationalization_de.ts'...

Found3sourcetext(s)(3newand0alreadyexisting)

Now,opentheInternationalization_de.tsfileinQtLinguist.TheoverviewUIofQtLinguistisdisplayedinthefollowingscreenshot:

Page 204: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

Contextliststhesourcetextcontext,whichistheclassnameinmostcases,whileStringscontainsallthetranslatablestrings.SourcesandFormsdisplaysthecorrespondinglocationofthestring,eitherasapieceofcodeoraUIform.Beneaththemisthetranslationarea,whichletsyouinputthetranslationandcomments,ifthereareany.

Inadditiontotheoverview,theiconinfrontofeachentryisnoteworthy.Ayellowquestionmark(?)simplymeansthereisnotranslationcurrently,whileagreencheckmarkmeansaccepted/correct,andayellowcheckmarkstandsforaccepted/warnings.Youmayalsoencounteraredexclamationmark(!),whichindicateswarnings.Thesharpsymbol(#)infrontofabutton'stextintheSourcesandFormspaneindicatesuntranslated,andpossiblytranslatable,strings.QtLinguistchecksstringtranslationsautomaticallyaccordingtoitsownalgorithm,whichmeansthatitmaygiveafalsewarning.Inthiscase,simplyignorethewarningandacceptthetranslation.

You'llfindthatthelabeltextisn'tamongSourcetext.Thisisbecauseweuncheckedthetranslatableproperty.Now,inputGermantranslationsinthetranslationareaandclickontheDoneandNextbuttoninthetoolbar,thennavigatetoTranslation|DoneandNext.Or,evenquicker,pressCtrl+Entertoacceptthetranslation.Whenyou'vefinished,clickontheSavebutton,andthenexitQtLinguist.

Page 205: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

Althoughit'srecommendedtouseQtLinguistfortranslationtasks,it'sviabletouseanormaltexteditortoedittheTSfiledirectly.TheTSfileisXML-formattedandshouldbesupportedwellbyothereditors.

Aftertranslating,returntoQtCreatorandrunthelreleasecommandtogeneratetheInternationalization_de.qmfile.Atthecurrentstage,yourprojectfoldershouldcontainboththeTSandQMfiles,asshowninthefollowingscreenshot:

NoteNotethatfileiconsmaydifferslightlyonyourcomputersbecauseofdifferentoperatingsystemand(or)softwareinstallations.

WealreadyproducedtheQMfile;it'snowtimetomodifythemain.cppfileinordertoloadthetranslationintothisapplication.

#include"mainwindow.h"

#include<QApplication>

#include<QTranslator>

intmain(intargc,char*argv[])

{

QApplicationa(argc,argv);

Page 206: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

QTranslatortranslator;

translator.load(QLocale::German,"Internationalization",

"_");

a.installTranslator(&translator);

MainWindoww;

w.show();

returna.exec();

}

Here,QTranslatorisusedtoloadtheGermantranslation.BeforeweinstalltranslatorintoQApplication,wehavetoloadaQMfilebycallingtheloadfunction.ThiswillloadthetranslationfilewhosefilenameconsistsofInternationalizationfollowedby_andtheUIlanguagename(whichisdeinthiscase)and.qm(thedefaultvalue).Thereisasimplifiedoverloadedloadfunction.Ourequivalentisasfollows:

translator.load("Internationalization_de");

Usually,itwouldbebettertocallthepreviousloadfunctionbecauseitusesQLocale::uiLanguages(),anditwillalsoformatdatesandnumbersifthey'renecessaryforthenewlocale.Whicheveryouchoose,alwaysrememberthatifyouloadthetranslationaftertheMainWindoww;line,MainWindowwon'tbeabletousethetranslationatall.

Ifyouruntheapplicationnow,theapplicationwon'tdisplayGermanyet.Why?ThisissimplybecauseQTranslatorcan'tfindtheInternationalization_de.qmfile.Therearelotsofwaystosolvethisproblem.Theneatestwayistochangetheworkingdirectory,whilerunningtheapplicationinQtCreator.

1. SwitchtotheProjectsmode.2. SwitchtoRunSettings.3. ChangeWorkingdirectorytoyourprojectsourcedirectorywhereyouputthe

Internationalization_de.qmfile.

Now,runitagain;you'llseeGermantextonthescreen,asfollows:

Page 207: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

ThelabelisdisplayedinEnglishasweexpected,whereasthewindowtitleandbuttontextaredisplayedinGerman.

Youmaythinkthissolutionpointless,sincetheGermantranslationisloadeddespitethesystemlocalesetting.Well,theapplicationcanloadthetranslationaccordingtothesystemlocalewithonlyonemodification;thatis,changingthetranslatorloadlinetotheoneshownhere:

translator.load(QLocale::system().language(),

"Internationalization","_");

Here,system()isastaticmemberfunctionoftheQLocaleclass,whichreturnsaQLocaleobjectthatinitializedwiththesystemlocale.Wethencallthelanguage()functiontogetthelanguageofthecurrentlocale.

Page 208: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

DisambiguatingidenticaltextsIfthereareidenticaltexts,thedefaultbehavioristotreatthemasthetextswiththesamemeaning.Thiscouldeffectivelysavetranslatorsfromtranslatingthesametexts.Meanwhile,thisdoesn'tholdtrueallthetime.Forinstance,thewordopencanbeusedasanounoranadjective,whichmaybedifferentwordsinotherlanguages.Thankfully,it'spossibleandeasytodisambiguateidenticaltextsinQt.

Now,let'saddaPushButtonandopenButtonbetweentransButtonandnonTransLabel.UseOpenasitstext,andtheneditmainwindow.h.AddanewprivateslotnamedonOpenButtonClicked(),whichisusedtohandletheeventwhenopenButtongetsclicked.Therelevantsourcefile,mainwindow.cpp,ispastedasfollows:

#include<QMessageBox>

#include"mainwindow.h"

#include"ui_mainwindow.h"

MainWindow::MainWindow(QWidget*parent):

QMainWindow(parent),

ui(newUi::MainWindow)

{

ui->setupUi(this);

connect(ui->openButton,&QPushButton::clicked,this,

&MainWindow::onOpenButtonClicked);

}

MainWindow::~MainWindow()

{

deleteui;

}

voidMainWindow::onOpenButtonClicked()

{

QMessageBox::information(this,tr("Dialog"),tr("Open"));

}

First,weconnecttheclickedsignalofopenButtontotheonOpenButtonClickedslotofMainWindowintheconstructorofMainWindow.Then,wesimplyusethestaticmemberfunction,information,ofQMessageBoxtopop-upaninformationdialog,usingDialogasthetitleandOpenasitscontext.Don'tforgettousethetr()functiontomakethesestringstranslatable.

Now,runlupdateandopentheTSfileinQtLinguist.ThereisonlyoneOpenstringintheStringspanel,asshownhere:

Page 209: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

However,Openintheinformationdialogissupposedtohaveanadjective,whichshouldn'tbemixedupwiththetextinopenButton.It'sacommentthatweneedtoseparatethisOpenfromtheotherOpen.ModifytheonOpenButtonClickedfunctioninmainwindow.cpp:

voidMainWindow::onOpenButtonClicked()

{

QMessageBox::information(this,tr("Dialog"),tr("Open",

"adj."));

}

Here,thesecondargumentofthetr()functionisthecomment.Differentcommentsstandfordifferenttexts.Inthisway,lupdatewilltreatthemasnonidenticaltexts.Rerunlupdate,andyou'reabletotranslatetwoOpenstringsinQtLinguist.TheDevelopercommentscolumninthetranslationareaisshownhere.QtLinguistwillalsoshowtwotranslatableOpenstrings.

TheequivalentpropertyintheDesignmodeforopenButtonisdisambiguationunder

Page 210: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

thetextproperty.Aftertranslation,executelrelease,andthenreruntheapplicationandthetwoOpenstringsshouldhavetwodifferenttranslations,whichisdemonstratedhere:

Page 211: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

ChanginglanguagesdynamicallySometimes,peoplewanttouselanguagesotherthantheonespecifiedbythesystemlocale.Thisisamatterofapplicationofthecustomizedsettings.Thisusuallymeansrestartingtheapplicationinordertoloadthecorrespondingtranslationfile.Thisispartlybecausechangingthelanguagedynamicallyrequiresadditionalwork.However,it'sfeasibleandcanbedonewithsomelines.What'smoreimportantisthatitdeliversabetteruserexperience!

Let'saddanewpushbuttontoMainWindow.NameitloadButtonandchangeitstexttoLoad/UnloadTranslation.Then,editthemain.cppfileintheEditmode.RemoveallQTranslatorrelatedlines,aswe'llbeimplementingthisdynamiclanguageswitchintheMainWindowclass.Themain.cppfileshouldlookliketheoriginallygeneratedoneasfollows:

#include"mainwindow.h"

#include<QApplication>

intmain(intargc,char*argv[])

{

QApplicationa(argc,argv);

MainWindoww;

w.show();

returna.exec();

}

Now,editmainwindow.h,asweneedtodeclaresomemembershere:

#ifndefMAINWINDOW_H

#defineMAINWINDOW_H

#include<QMainWindow>

#include<QTranslator>

namespaceUi{

classMainWindow;

}

classMainWindow:publicQMainWindow

{

Q_OBJECT

public:

explicitMainWindow(QWidget*parent=0);

~MainWindow();

private:

Page 212: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

Ui::MainWindow*ui;

QTranslator*deTranslator;

booldeLoaded;

privateslots:

voidonOpenButtonClicked();

voidonLoadButtonClicked();

protected:

voidchangeEvent(QEvent*);

};

#endif//MAINWINDOW_H

Asyoucantell,wemovedQTranslatorhere,nameditdeTranslator,anduseditasapointerwiththedeLoadedvariabletosuggestwhetherornotwe'vealreadyloadedtheGermantranslation.ThefollowingonLoadButtonClickedisaprivateslotfunction,whichwillbeconnectedtotheclickedsignalofloadButton.Lastbutnotleast,wereimplementchangeEvent,sothatwecantranslatetheentireuserinterfaceonthefly.It'llbeclearinthemainwindow.cppsourcefile,whereitispastedasfollows:

#include<QMessageBox>

#include"mainwindow.h"

#include"ui_mainwindow.h"

MainWindow::MainWindow(QWidget*parent):

QMainWindow(parent),

ui(newUi::MainWindow)

{

ui->setupUi(this);

deTranslator=newQTranslator(this);

deTranslator->load(QLocale::German,"Internationalization",

"_");

deLoaded=false;

connect(ui->openButton,&QPushButton::clicked,this,

&MainWindow::onOpenButtonClicked);

connect(ui->loadButton,&QPushButton::clicked,this,

&MainWindow::onLoadButtonClicked);

}

MainWindow::~MainWindow()

{

deleteui;

}

voidMainWindow::onOpenButtonClicked()

{

QMessageBox::information(this,tr("Dialog"),tr("Open",

"adj."));

Page 213: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

}

voidMainWindow::onLoadButtonClicked()

{

if(deLoaded){

deLoaded=false;

qApp->removeTranslator(deTranslator);

}

else{

deLoaded=true;

qApp->installTranslator(deTranslator);

}

}

voidMainWindow::changeEvent(QEvent*e)

{

if(e->type()==QEvent::LanguageChange){

ui->retranslateUi(this);

}

else{

QMainWindow::changeEvent(e);

}

}

Intheconstructor,weinitializedeTranslatorandloadtheGermantranslation,whichisalmostidenticaltowhatwedidinmain.cppbefore.Then,wesetdeLoadedtofalse,indicatingthattheGermantranslationisnotinstalledyet.Next,thisisfollowedbyaconnectstatement.

Now,let'slookintotheonLoadButtonClickedfunctiontoseewhatwillhappeniftheloadButtongetsclicked.WesetdeLoadedtofalseandremovedeTranslatorifit'salreadyloaded.Otherwise,weinstalldeTranslatorandsetdeLoadedtotrue.RememberthatqAppisapredefinedmacrothatsimplyreferstothecurrentinstanceofQCoreApplication.BothinstallTranslatorandremoveTranslatorwillpropagatetheeventtoallthetop-levelwindows,thatistosay,changeEventofMainWindowwillbetriggeredinthiscase.

Inordertoupdateallthetextaccordingtothetranslator,wehavetoreimplementchangeEvent.Inthisreimplementedfunction,wecalltheretranslateUifunctiontoretranslateMainWindowiftheeventislanguageChange.Otherwise,wesimplycalltheinheritedanddefaultQMainWindow::changeEventfunction.

Whenyoufirstlystarttheapplication,it'lldisplayEnglishtext.

Page 214: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

OnceyouclickontheLoad/UnloadTranslationbutton,alltranslatableandtranslatedtextwillshowinGerman.

It'lldisplayinEnglishifyouclickthebuttonagain.Inadditiontoanontranslatablelabel,loadButtonwillnotbenottranslatedeither.Thisisbecausewedidn'ttranslatethebuttonatall.However,asyoucansee,thelackofsometranslationswon'tpreventtheapplicationfromloadingothertranslatedtexts.

Page 215: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

TranslatingQtQuickapplicationsTheprocedureoftranslatingaQtQuickapplicationissimilartoaQtWidgetsapplication.We'llwalkthroughtheprocesswithanotherexampleapplication.

CreateanewQtQuickapplicationprojectandnameitInternationalization_QML.Thegeneratedmain.qmlfilehasalreadyaddedaqsTr()functionforus.ThecontentsmaydifferslightlyinalaterversionofQtCreatorand(or)QtLibrary.However,itshouldlooksimilartothisone:

importQtQuick2.3

importQtQuick.Controls1.2

ApplicationWindow{

visible:true

width:640

height:480

title:qsTr("HelloWorld")

menuBar:MenuBar{

Menu{

title:qsTr("File")

MenuItem{

text:qsTr("&Open")

onTriggered:console.log("Openactiontriggered");

}

MenuItem{

text:qsTr("Exit")

onTriggered:Qt.quit();

}

}

}

Text{

text:qsTr("HelloWorld")

anchors.centerIn:parent

}

}

Now,let'sedittheInternationalization_QML.proprojectfile,whosemodifiedversionispastedasfollows:

TEMPLATE=app

QT+=qmlquickwidgets

SOURCES+=main.cpp

RESOURCES+=qml.qrc

Page 216: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

lupdate_only{

SOURCES+=main.qml

}

TRANSLATIONS=Internationalization_QML_de.ts

#AdditionalimportpathusedtoresolveQMLmodulesinQt

#Creator'scodemodel

QML_IMPORT_PATH=

#Defaultrulesfordeployment.

include(deployment.pri)

InadditiontotheTRANSLATIONSline,wealsoaddalupdate_onlyblock.Itiscrucialinthiscase.

NoteWeprobablydon'tneedthisblockintheQt/C++projectsbecausethelupdatetoolextractsthetranslatablestringsfromSOURCES,HEADERS,andFORMS.

However,thismeansthatallthestringslocatedelsewherewon'tbefound,notevensayingtranslating.Ontheotherhand,theqmlfilesarenottheC++sourcefilesthataregoingtobecompiledbytheC++compiler.Inthiscase,weuselupdate_onlytorestrictthoseSOURCES,whichareonlyavailableforlupdate.

Now,executinglupdatecangeneratethetranslationsourcefileforus.Similarly,weuseQtLinguisttotranslatetheInternationalization_QML_de.tsfile.Then,executelreleasetogeneratetheQMfile.

Toloadthetranslation,weneedtomodifymain.cppintotheoneshownhere:

#include<QApplication>

#include<QQmlApplicationEngine>

#include<QTranslator>

intmain(intargc,char*argv[])

{

QApplicationapp(argc,argv);

QTranslatortranslator;

translator.load(QLocale::German,"Internationalization_QML",

"_");

app.installTranslator(&translator);

QQmlApplicationEngineengine;

Page 217: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

engine.load(QUrl(QStringLiteral("qrc:/main.qml")));

returnapp.exec();

}

Also,weneedtochangeWorkingdirectorytothisproject'sdirectoryinRunSettingsintheProjectsmode.Now,runtheapplicationagain;weshouldbeabletoseeGermantextonthescreen,aswecaninthefollowingscreenshot:

Thereisanalternativewaytoloadthetranslationsfile,whichdoesn'tneedtochangeWorkingdirectory.Firstly,changethetranslator.loadlineinmain.cpptothefollowingone:

translator.load(QLocale::German,"Internationalization_QML",

"_",":/");

Wespecifythedirectorythatthetranslatorshouldsearch.Inthiscase,it's":/",whichisthetopdirectoryinsideResources.Pleasedon'tprependqrctothedirectorystring;thiswillcausetranslatortobeunabletofindtheQMfile.Acolon(:)issufficientheretoindicatethatthereisaqrcpathinsideResources.

Page 218: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

Youcaneithercreateanewqrcfile,orsimilartowhatwedo,addInternationalization_QML_de.qmtothecurrentqml.qrcfile.

1. Right-clickontheqml.qrcfileunderResourcesinProjectsEditor.2. SelectOpeninEditor.3. NavigatetoAdd|AddFilesonthelower-rightpanel.4. SelecttheInternationalization_QML_de.qmfileandclickonOpen.

Now,theInternationalization_QML_de.qmfileshoulddisplayonbothEditorandtheProjectstreelikethefollowingscreenshot:

GototheProjectsmodeandresetWorkingdirectoryinRunSettings.Then,runtheapplicationagain;theGermantranslationshouldstillloadsuccessfully.

Sofar,thereisnohugedifferencebetweenQtandQtQuick.However,it'stedioustoachievedynamictranslationinstallationandremovalinQtQuick.YouhavetowriteaC++classthatinstallsandremovethetranslator,whichthenemitsasignalindicatingthatthereisachangetothetext.Therefore,thebestpracticefortheQtQuickapplicationistomakelanguageasetting.Theusercanthenloaddifferenttranslations.Itneedsarestartoftheapplication,though.

Page 219: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

SummaryYou'renowabletomakeyourapplicationmorecompetitivebyaddingsupportforotherlanguagesnow.Besides,thesupereasytouseQtLinguist,whichisalsoacross-platformtoolprovidedbyQt,isalsocoveredinthischapter.Inadditiontotheskillsyoulearnt,youcanalsotellthatQt/C++stillholdsagreatadvantageoverQtQuick/QMLintermsofAPIsandfeatures.

Inthenextchapter,we'regoingtomakeourQtapplicationsredistributableanddeploythemonotherdevices.

Page 220: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

Chapter9.DeployingApplicationsonOtherDevicesAfterdevelopment,it'stimetodistributeyourapplication.We'lluseanexampleapplication,Internationalization,fromthepreviouschaptertodemonstratehowtospreadyourQtapplicationtoWindows,Linux,andAndroid.Thefollowingtopicswillbecoveredinthischapter:

ReleasingQtapplicationsonWindowsCreatinganinstallerPackagingQtapplicationsonLinuxDeployingQtapplicationsonAndroid

ReleasingQtapplicationsonWindowsAfterthedevelopmentstage,youcanbuildyourapplicationusingreleaseasthebuildconfiguration.Inthereleaseconfiguration,yourcompilerwilloptimizethecodeandwon'tproducedebugsymbols,whichinturnreducesthesize.Pleaseensurethattheprojectisinthereleaseconfiguration.

Beforewejumpintothepackagingprocedure,I'dliketotalkaboutthedifferencebetweenstaticanddynamiclinking.YouhaveprobablybeenusingdynamiclinkingofQtlibrariesthroughoutthisbook.ThiscanbeconfirmedifyoudownloadtheCommunityEditionfromtheQtwebsite.

So,whatdoesdynamiclinkingmean?Well,itmeansthatwhenanexecutablefilegetsexecuted,theoperatingsystemwillloadandlinkthenecessarysharedlibrariesatruntime.Inotherwords,you'llseealotof.dllfilesonWindowsand.sofilesontheUnixplatforms.Thistechniqueallowsdeveloperstoupdatethesesharedlibrariesandtheexecutableseparately,whichmeansthatyoudon'tneedtorebuildtheexecutablefileifyouchangesharedlibraries,solongastheirABIsarecompatible.Althoughthismethodismoreflexible,developersarewarnedtotakecaretoavoidDLLHell.

ThemostcommonlyusedsolutiontoDLLHellonWindowsistochoosestaticlinkinginstead.Bycontrast,staticlinkingwillresolveallthefunctioncallsandvariablesatcompiletimeandcopythemintothetargettoproduceastandaloneexecutable.Theadvantagesareobvious.Firstly,youdon'tneedtoshipallnecessaryandsharedlibraries.Therewon'tbeDLLHellinthissituation.OnWindows,staticlibrariesmayget.libor.aasextensionsdependingonthecompileryouuse,whereasthey

Page 221: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

usuallyget.aontheUnixplatforms.

Tomakeaclearcomparison,atableismadeforyoutoseethedifferencesbetweenthedynamicandstaticlinking:

DynamicLinking StaticLinking

Librarytypes Sharedlibraries Staticlibraries

Executablesize Considerablysmaller Greaterthandynamicallylinked

Libraryupdates Onlylibrariesthemselves Executablefileneedstoberebuilt

Incompatiblelibraries

Needtotakecaretoavoidthis Won'thappen

However,ifthesharedlibrariesshippedwithdynamicallylinkedexecutablefilesarecountedaspartofthepackage,thedynamicstylepackagewillbelargerthanthestaticallylinkedstandaloneexecutablefiles.

Now,backtothetopic!SincethereisnostandardQtruntimelibraryinstallerforWindows,thebestroutineistoproduceastaticallylinkedtargetbecausethepackagetobereleasedwillbesmaller,andtheexecutableisimmunetoDLLHell.

However,asmentionedpreviously,theQtlibrariesyoudownloadedcanonlybeusedfordynamiclinkingapplicationsbecausetheyaresharedlibraries.ItisviabletocompileQtasstaticlibraries.However,beforeyouproceed,youneedtoknowthelicensesofQt.

Currently,inadditiontotheQtOpenSourceLicense,thereisalsotheQtCommercialLicense.Foropensourcelicenses,mostoftheQtlibrariesarelicensedunderTheGNULesserGeneralPublicLicense(LPGL).Inthiscase,ifyoubuildyourapplicationstaticallylinkedwiththeQtlibraries,yourapplicationissubjecttoprovideusersthesourcecodeofyourapplicationunderLGPL.Yourapplicationmaystayproprietaryandclosedsourceifit'sdynamicallylinkedwiththeQtlibraries.Inother

Page 222: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

words,ifyouwanttolinkanapplicationstaticallyandkeepitproprietary,youhavetopurchasetheQtcommerciallicense.FordetailsaboutQtlicensing,refertohttp://www.qt.io/licensing/.

Ifyoudecidetousestaticlinking,youmighthavetocompiletheQtlibrariesstaticallybeforebuildingyourapplication.Inthiscase,theexecutabletargetistheonlythingthatneedstobepackagedandreleased.Don'tforgettheQMfilesifyourapplicationhasmulti-languagesupport,asmentionedpreviously.

Ontheotherhand,ifyouwanttogothedynamicway,it'dneedsomeextraeffort.Firstly,therearesomecoreDLLsthathavetoexistandthelistisdifferentdependingonthecompiler.ThefollowingtableincludesbothMSVCandMinGW/GCCscenarios:

MSVC2013 MinGW/GCC

msvcp120.dll libgcc_s_dw2-1.dll

msvcr120.dll libstdc++-6.dll

libwinpthread-1.dll

TherearecommonDLLsthatneedtobeincluded,suchasicudt53.dll,icuin53.dll,andicuuc53.dll.YoucanfindthesefilesintheQtlibrariesdirectory.TakeMinGW/GCCasanexample;they'relocatedinQT_DIR\5.4\mingw491_32\binwhereQT_DIRistheQtinstallationpath,suchasD:\Qt.NotethatthelaterversionsofQtmayhaveslightlydifferentfilenames.

Besides,thereisnoneedtoshipmsvcp120.dllandmsvcr120.dllifthetargetusershaveinstalledVisualC++RedistributablePackagesforVisualStudio2013,whichcanbedownloadedfromhttp://www.microsoft.com/en-ie/download/details.aspx?id=40784.

Afterthis,youmaywanttocheckotherDLLsyou'llneedbylookingintotheprojectfile.TaketheInternationalizationprojectasanexample.Itsprojectfile,Internationalization.pro,givesusaclue.TherearetwolinesrelatedtotheQTconfiguration,shownasfollows:

Page 223: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

QT+=coregui

greaterThan(QT_MAJOR_VERSION,4):QT+=widgets

TheQTvariableincludesthecoreguiwidgets.Infact,alltheQtapplicationswillincludecoreatleast,whileothersaredependent.Inthiscase,wehavetoshipQt5Core.dll,Qt5Gui.dll,andQt5Widgets.dllalongwiththeexecutabletarget.

Now,buildtheInternationalizationprojectwithMinGW/GCC.Theexecutabletarget,Internationalization.exe,shouldbelocatedinsidethereleasefolderofthebuilddirectory,whichcanbereadfromtheProjectsmode.Next,wecreateanewfoldernamedpackageandcopytheexecutablefilethere.Then,wecopytheneededDLLstopackageaswell.Now,thisfoldershouldhaveallthenecessaryDLLsasshownhere:

Inmostcases,ifarequiredlibraryismissing,theapplicationwon'trunwhiletheoperatingsystemwillpromptthemissinglibraryname.Forinstance,ifQt5Widgets.dllismissing,thefollowingsystemerrordialogwillshowupwhenyoutrytorunInternationalizationi.exe:

Basically,theroutineistocopythemissinglibrariestothesamefolderthattheapplicationisin.Besides,youcanusesometoolssuchasDependencyWalkertogetthelibrarydependencies.

Page 224: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

Pleasedon'tuseDLLsfromtheQtEditorfolder.ThisversionisoftendifferentfromQtLibrariesyou'veused.Inadditiontotheselibraries,youmayhavetoincludealltheresourcesthatyourapplicationisgoingtouse.Forexample,theQMfilesusedfortranslation,thatis,tocopytheInternationalization_de.qmfileinordertoloadtheGermantranslation.

Thefilelistisasfollows:

icudt53.dll

icuin53.dll

icuuc53.dll

Internationalization.exe

Internationalization_de.qm

libgcc_s_dw2-1.dll

libstdc++-6.dll

libwinpthread-1.dll

Qt5Core.dll

Qt5Gui.dll

Qt5Widgets.dll

Don'tforget,thisisthecaseforMinGW/GCCinQt5.4.0,whiledifferentversionsandcompilersmighthaveaslightlydifferentlist,aswediscussedbefore.

Afterthisfirst-timepreparation,tosomeextentthislistisfixed.YouonlyneedtochangetheexecutabletargetandtheQMfileifit'schanged.Aneasywaytodothisistocompressallofthemintarball.

Page 225: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

CreatinganinstallerAlthoughit'squicktouseanarchivefiletodistributeyourapplication,itseemsmoreprofessionalifyouprovideuserswithaninstaller.QtoffersQtInstallerFrameworkwhoselatestopensourceversion,1.5.0fornow,canbeobtainedfromhttp://download.qt.io/official_releases/qt-installer-framework/1.5.0/.

Forthesakeofconvenience,let'screateafoldernameddistundertheQtInstallerFrameworkinstallationpath,D:\Qt\QtIFW-1.5.0.Thisfolderisusedtostorealltheapplicationprojectsthatneedtobepackaged.

Then,createafoldernamedinternationalizationunderdist.Insideinternationalization,createtwofolders,configandpackages.

Thenameofthedirectoryinsidethepackagesdirectoryactsasadomain-like,orsayJava-style,identifier.Inthisexample,wehavetwopackages,oneistheapplicationwhiletheotheroneisatranslation.Therefore,itaddstothetwofoldersinthepackagesdirectory,com.demo.internationalization,andcom.demo.internationalization.translation,respectively.Therewillbemetaanddatadirectoriespresentinsideeachofthem,sotheoveralldirectorystructureissketchedasfollows:

Page 226: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

Let'sedittheglobalconfigurationfile,config.xml,whichisfirstinsidetheconfigdirectory.Youneedtocreateonefilenamedconfig.xml.

NoteAlwaysremembernottousetheWindowsbuilt-inNotepadtoeditthisfile,orinfactanyfile.YoumayeitheruseQtCreatororotheradvancededitors,suchasNotepad++,toeditit.ThisissimplybecauseNotepadlacksofalotoffeaturesasacodeeditor.

Inthisexample,theconfig.xmlfile'scontentispastedhere:

<?xmlversion="1.0"encoding="UTF-8"?>

<Installer>

<Name>Internationalization</Name>

<Version>1.0.0</Version>

<Title>InternationalizationInstaller</Title>

<Publisher>Packt</Publisher>

<TargetDir>@homeDir@/Internationalization</TargetDir>

Page 227: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

<AdminTargetDir>@rootDir@/Internationalization</AdminTargetDir

>

</Installer>

Foraminimumconfig.xmlfile,theelements<Name>and<Version>mustexistin<Installer>.Allotherelementsareoptional,butyoushouldspecifythemifthereisaneed.Meanwhile,<TargetDir>and<AdminTargetDir>maybeabitconfusing.Theybothspecifythedefaultinstallationpath,where<AdminTargetDir>istospecifytheinstallationpathwhenitgainedadministrativerights.Theotherelementsareprettymuchself-explanatory.Thereareotherelementsthatyoucansettocustomizetheinstaller.Formoredetails,refertohttp://doc.qt.io/qtinstallerframework/ifw-globalconfig.html.

Let'snavigateintothemetafolderinsidecom.demo.internationalization.Thisdirectorycontainsthefilesthatspecifythesettingsfordeploymentandinstallation.Allthefilesinthisdirectory,exceptforlicenses,won'tbeextractedbytheinstaller,andneitherwilltheybeinstalled.Theremustbeatleastapackageinformationfile,suchaspackage.xml.Thefollowingexample,package.xml,incom.demo.internationalization/metaisshownhere:

<?xmlversion="1.0"encoding="UTF-8"?>

<Package>

<DisplayName>CoreApplication</DisplayName>

<Description>Essentialpartof

Internationalization</Description>

<Version>1.0.0</Version>

<ReleaseDate>2014-12-27</ReleaseDate>

<Name>com.demo.internationalization</Name>

<Licenses>

<Licensename="LicenseAgreement"file="license.txt"/>

</Licenses>

<Default>true</Default>

<ForcedInstallation>true</ForcedInstallation>

</Package>

The<Default>elementspecifieswhetherthispackageshouldbeselectedbydefault.Atthesametime,weset<ForcedInstallation>totrue,indicatingthattheenduserscan'tdeselectthispackage.Whilethe<Licenses>elementcanhavemultiplechildren<License>,inthiscaseweonlyhaveone.Wehavetoprovidethelicense.txtfile,whosecontentisjustasinglelinedemonstration,asshownhere:

Thisisthecontentoflicense.txt.

Thefollowingpackage.xmlfile,whichislocatedincom.demo.internationalization.translation/meta,hasfewerlines:

Page 228: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

<?xmlversion="1.0"encoding="UTF-8"?>

<Package>

<DisplayName>GermanTranslation</DisplayName>

<Description>Germantranslationfile</Description>

<Version>1.0.0</Version>

<ReleaseDate>2014-12-27</ReleaseDate>

<Name>com.demo.internationalization.translation</Name>

<Default>false</Default>

</Package>

Thedifferencebetween<DisplayName>and<Description>isdemonstratedbythefollowingscreenshot:

The<Description>elementisthetextthatdisplaysontheright-handsidewhenthepackagegetsselected.It'salsothetextthatpopsupasthetooltipwhenthemousehoversovertheentry.Youcanalsoseetherelationshipbetweenthesetwopackages.Asthenamecom.demo.internationalization.translationsuggests,itisasubpackageofcom.demo.internationalization.

Thelicenseswillbedisplayedafterthisstepandareshowninthefollowingscreenshot.Ifyousetmultiplelicenses,thedialogwillhaveapaneltoviewthoselicensesseparately,similartotheoneyouseewhenyouinstallQtitself.

Page 229: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

Formoresettingsinthepackage.xmlfile,refertohttp://doc.qt.io/qtinstallerframework/ifw-component-description.html#package-information-file-syntax.

Bycontrast,thedatadirectoriesstoreallthefilesthatneedtobeinstalled.Inthisexample,wekeepallfilespreparedpreviouslyinthedatafolderofcom.demo.internationalization,exceptfortheQMfile.TheQMfile,Internationalization_de.qm,iskeptinthedatafolderinsidecom.demo.internationalization.translation.

Afteralltheinitialpreparation,wecometothefinalsteptogeneratetheinstallerapplicationofthisproject.Dependingonyouroperatingsystem,openCommandPromptorTerminal,changingthecurrentdirectorytodist/internationalization.Inthiscase,it'sD:\Qt\QtIFW-1.5.0\dist\internationalization.Then,executethefollowingcommandtogeneratetheinternationalization_installer.exeinstallerfile:

..\..\bin\binarycreator.exe-cconfig\config.xml-ppackages

internationalization_installer.exe

NoteOnUnixplatforms,includingLinuxandMacOSX,you'llhavetouseaslash(/)insteadofanti-slash(\),anddropthe.exesuffix,whichmakesthecommandslightlydifferent,asshownhere:

Page 230: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

../../bin/binarycreator-cconfig/config.xml-ppackages

internationalization_installer

Youneedtowaitforawhilebecausethebinarycreatortoolwillpackagefilesinthedatadirectoriesintothe7ziparchives,whichisatimeconsumingprocess.Afterthis,youshouldexpecttoseeinternationalization_installer.exe(orwithout.exe)inthecurrentdirectory.

Theinstallerismuchmoreconvenient,especiallyforabigapplicationprojectthathasseveraloptionalpackages.Besides,it'llregisterandlettheendusersuninstallthroughControlPanel.

Page 231: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

PackagingQtapplicationsonLinuxThingsaremorecomplicatedonLinuxthanonWindows.Therearetwopopularpackageformats:RPMPackageManager(RPM)andDebianBinaryPackage(DEB).RPMwasoriginallydevelopedforRedHatLinuxandit'sthebaselinepackageformatofLinuxStandardBase.It'smainlyusedonFedora,OpenSUSE,RedHatEnterpriseLinux,anditsderivatives;whilethelatterisfamousforbeingusedinDebiananditswell-knownandpopularderivative,Ubuntu.

Inadditiontotheseformats,thereareotherLinuxdistributionsusingdifferentpackageformats,suchasArchLinuxandGentoo.ItwilltakeextratimetopackageyourapplicationsfordifferentLinuxdistributions.

However,itwon'tbetootimeconsuming,especiallyforopen-sourceapplications.Ifyourapplicationisopensource,youcanrefertothedocumentationtowriteaformattedscripttocompileandpackageyourapplication.FordetailsoncreatinganRPMpackage,refertohttps://fedoraproject.org/wiki/How_to_create_an_RPM_package,whereasforDEBpackaging,refertohttps://www.debian.org/doc/manuals/maint-guide/index.en.html.ThereisanexamplelaterthatdemonstrateshowtopackageDEB.

Althoughit'sfeasibletopackproprietaryapplications,suchastheRPMandDEBpackages,theywon'tgetintotheofficialrepository.Inthiscase,youmaywanttosetuparepositoryonyourserverorjustreleasethepackagesviaafilehost.

Alternatively,youcanarchiveyourapplications,similartowhatwedoonWindows,andwriteashellscriptforinstallationanduninstallation.Inthisway,youcanuseonetarballorQtInstallerFrameworktocookaninstallerforvariousdistributions.But,don'teverforgettoaddressthedependenciesappropriately.TheincompatiblesharedlibraryissueisevenworseonLinux,becausealmostallthelibrariesandapplicationsarelinkeddynamically.Theworstpartistheincompatibilitybetweendifferentdistributions,sincetheymayusedifferentlibraryversions.Therefore,eithertakecareofthesepitfalls,orgothestaticlinkingway.

Aswementionedpreviously,staticallylinkedsoftwaremustbeopensourceunlessyouhavepurchasedtheQtcommerciallicense.Thisdilemmamakesthestaticallylinkedopensourceapplicationpointless.Thisisnotonlybecausedynamiclinkingisthestandardway,butalsobecausestaticallylinkedQtapplicationswon'tbeabletousethesystemthemeandcan'tbenefitfromsystemupgrades,whichisnotokaywhensecurityupdatesareinvolved.Anyway,youcancompileyourapplicationusingstaticlinkingifyourapplicationisproprietaryandyougetacommerciallicense.Inthiscase,justlikestaticlinkingonWindows,youonlyneedtoreleasethetarget

Page 232: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

executablefileswiththenecessaryresources,suchasiconsandtranslations.It'snoteworthythatevenifyoubuildstaticallylinkedQtapplications,it'sstillimpossibletorunthemonanyLinuxdistributions.

Therefore,therecommendedwayistoinstallseveralmainstreamLinuxdistributionsonvirtualmachines,andthenusethesevirtualmachinestopackageyourdynamicallylinkedapplicationastheirownpackageformats.Thebinarypackagedoesn'tcontainsourcecode,andit'salsoacommonpracticetostripthesymbolsfromthebinarypackage.Inthisway,yoursourcecodeforproprietarysoftwarewon'tbeleakedthroughthesepackages.

WestilluseInternationalizationasanexamplehere.Let'sseehowtocreateaDEBpackage.ThefollowingoperationsweretestedonthelatestDebianWheezy;laterversionsordifferentLinuxdistributionsmightbeslightlydifferent.

Beforewepackagetheapplication,wehavetoedittheprojectfile,Internationalization.pro,tomakeitinstallableasfollows:

QT+=coregui

greaterThan(QT_MAJOR_VERSION,4):QT+=widgets

TARGET=Internationalization

TEMPLATE=app

SOURCES+=main.cpp\

mainwindow.cpp

HEADERS+=mainwindow.h

FORMS+=mainwindow.ui

TRANSLATIONS=Internationalization_de.ts

unix:{

target.path=/opt/internationalization_demo

qmfile.path=$$target.path

qmfile.files=Internationalization_de.qm

INSTALLS+=target\

qmfile

}

Thereisaconceptinqmakecalledinstallset.Eachinstallsethasthreemembers:path,files,andextra.Thepathmemberdefinesthedestinationlocation,whilefilestellsqmakewhatfilesshouldbecopied.Youcanspecifysomecommandsthatneedtobeexecutedbeforeotherinstructionsinextra.

Page 233: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

TARGETisabitspecial.Firstly,it'sthetargetexecutable(orlibrary),whileontheotherhand,italsoimpliestarget.files.Therefore,weonlyneedtospecifythepathoftarget.Wealsousethesamepathforqmfile,whichincludestheQMfile.Don'tforgettouseadoubledollarsign,$$,touseavariable.Lastly,wesettheINSTALLSvariable,whichdefineswhatistobeinstalledwhenmakeinstalliscalled.TheunixbracketsareusedtolimitthelinesonlyreadbyqmakeontheUnixplatforms.

Now,wecangetintotheDEBpackagingpartbyperformingthefollowingsteps:

1. Changeyourworkingdirectory(currentdirectory)totherootoftheproject,thatis,~/Internationalization.

2. Createanewfoldernameddebian.3. Createthefourrequiredfilesinthedebianfolder:control,copyright,

changelog,andrules,respectively.Then,createanoptionalcompatfileinthedebianfolderaswell.

Thecontrolfiledefinesthemostbasicyetmostcriticalthings.Thisfileisallaboutthesourcepackageandthebinarypackage(s).Thecontrolfileofourexampleispastedhere:

Source:internationalization

Section:misc

Priority:extra

Maintainer:SymeonHuang<[email protected]>

Build-Depends:debhelper(>=9),

qt5-qmake,

qtbase5-dev,

qtbase5-private-dev

Standards-Version:3.9.6

Package:internationalization

Architecture:any

Depends:${shlibs:Depends},${misc:Depends}

Description:AnexampleofQt5Blueprints

Thefirstparagraphistocontrolinformationforasource,whereaseachofthefollowingsetsdescribeabinarypackagethatthesourcetreebuilds.Inotherwords,onesourcepackagemaybuildseveralbinarypackages.Inthiscase,webuildonlyonebinarypackagewhosenameisthesameasSourceandinternationalization.

IntheSourceparagraph,SourceandMaintaineraremandatorywhileSection,Priority,andStandards-Versionarerecommended.Sourceidentifiesthesourcepackagename,whichcan'tincludeuppercaseletters.Meanwhile,Maintainercontainsthemaintainerpackage'snameandthee-mailaddressintheRFC822format.TheSectionfieldspecifiesanapplicationareainwhichthepackagehasbeenclassified.Priorityisaself-explanatoryfield,indicatinghowimportantthispackage

Page 234: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

is.Lastly,Standards-Versiondescribesthemostrecentversionofthestandardswithwhichthepackagecomplies.Inmostcases,youshouldusethelateststandardversion,3.9.6fornow.Thereareotherfieldsthatmaybeusefulbutoptional.Formoredetails,refertohttps://www.debian.org/doc/debian-policy/ch-controlfields.html.

YoucanspecifycertainpackagesneededforbuildinginBuild-Depends,similartoqt5-qmakeandqtbase5-devinourexample.They'reonlydefinedforbuildingprocessesandwon'tbeincludedinthedependenciesofbinarypackages.

ThebinaryparagraphsaresimilartothesourceexceptthatthereisnoMaintainer,butArchitectureandDescriptionaremandatorynow.Forbinarypackages,Architecturecanbeanyparticulararchitectureorsimplyanyorall.Specifyinganyindicatesthatthesourcepackageisn'tdependentonanyparticulararchitectureandhencecanbebuiltonanyarchitecture.Incontrasttothis,allmeansthatthesourcepackagewillproduceonlyarchitecture-independentpackages,suchasdocumentationsandscripts.

InDependsofthebinaryparagraph,weput${shlibs:Depends},${misc:Depends}insteadofparticularpackages.The${shlibs:Depends}linecanbeusedtoletdpkg-shlibdepsgeneratesharedlibrarydependenciesautomatically.Ontheotherhand,accordingtodebhepler,you'reencouragedtoput${misc:Depends}inthefieldtosupplement${shlibs:Depends}.Inthisway,wedon'tneedtospecifythedependenciesmanually,whichisareliefforpackagers.

Thesecondrequiredfile,copyright,istodescribethelicensesofthesourceaswellastheDEBpackages.Inthecopyrightfile,theformatfieldisrequiredwhiletheothersareoptional.Formoredetailsabouttheformatsofcopyright,refertohttps://www.debian.org/doc/packaging-manuals/copyright-format/1.0/.Thecopyrightfileinthisexampleisshownasfollows:

Format:http://www.debian.org/doc/packaging-manuals/copyright-

format/1.0/

Upstream-Contact:SymeonHuang<[email protected]>

File:*

Copyright:2014,2015SymeonHuang

License:Packt

License:Packt

ThispackageisreleasedunderPacktlicense.

ThefirstparagraphiscalledHeaderparagraph,whichisneededonceandonlyonce.TheFormatlineistheonlymandatoryfieldinthisparagraph,andinmostcases,thislineisthesame.ThesyntaxoftheUpstream-ContactfieldisthesameasMaintainerinthecontrolfile.

Page 235: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

ThesecondparagraphinthisfileisFilesparagraph,whichismandatoryandrepeatable.Intheseparagraphs,File,Copyright,andLicensearerequired.Weuseanasterisksign(*)indicatingthatthisparagraphappliestoallfiles.TheCopyrightfieldmaycontaintheoriginalstatementcopiedfromfilesorashortenedtext.TheLicensefieldinaFilesparagraphdescribesthelicensingtermsforthefilesdefinedbyFile.

FollowingtheFilesparagraph,theStand-alonelicenseparagraphisoptionalandrepeatable.WehavetoprovidethefulllicensetextifthelicenseisnotprovidedbyDebian.Generallyspeaking,onlycommonly-seenopen-sourcelicensesareprovided.Thefirstlinemustbeasinglelicenseshortname,whichisthenfollowedbyalicensetext.Foralicensetext,theremustbeatwospaceindentationineachline'shead.

Don'tbemisledbythechangelogfilename.Thisfilealsohasaspecialformatandisusedbydpkgtoobtaintheversionnumber,revision,distribution,andurgencyofyourpackage.It'sagoodpracticetodocumentallthechangesyouhavemadeinthisfile.However,youcanjustlistthemostimportantonesifyouhaveaversioncontrolsystem.Thechangelogfileinourexamplehasthefollowingcontents:

internationalization(1.0.0-1)unstable;urgency=low

*Initialrelease

--SymeonHuang<[email protected]>Mon,29Dec2014

18:45:31+0000

Thefirstlineisthepackagename,version,distribution,andurgency.Thenamemustmatchthesourcepackagename.Inthisexample,internationalizationisthename,1.0.0-1istheversion,unstablestandsforthedistribution,andurgencyislow.Then,useanemptylinetoseparatethefirstlineandlogentries.Inthelogentries,allthechangesthatyouwanttodocumentshouldbelisted.Foreachentry,therearetwospacesandanasterisksign(*)intheheader.Thelastpartofaparagraphisamaintainerlinethatbeginswithaspace.Formoredetailsaboutthisfileanditsformat,refertohttps://www.debian.org/doc/debian-policy/ch-source.html#s-dpkgchangelog.

Now,weneedtotakealookatwhatdpkg-buildpackagewilldotocreatethepackage.Thisprocessiscontrolledbytherulesfile;theexampleispastedhere:

#!/usr/bin/make-f

exportQT_SELECT:=qt5

%:

dh$@

Page 236: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

override_dh_auto_configure:

qmake

Thisfile,similartoMakefile,consistsofseveralrules.Also,eachrulebeginswithitstargetdeclaration,whiletherecipesarethefollowinglinesbeginningwiththeTABcode(notfourspaces).WeexplicitlysetQt5astheQtversion,whichcanavoidsomeissueswhenQt5coexistswithQt4.Thepercentagesign(%)isaspecialtargetandmeansanytargets,whichjustcallsthedhprogramwiththetargetname,whiledhisjustawrapperscript,whichrunsappropriateprogramsdependingonitsargument,therealtarget.

Therestofthelinesarecustomizationsforthedhcommand.Forinstance,dh_auto_configurewillcall./configurebydefault.Inourcase,weuseqmaketogenerateMakefileinsteadofaconfigurescript.Therefore,weoverridedh_auto_configurebyaddingtheoverride_dh_auto_configuretargetwithqmakeastherecipe.

Althoughthecompatfileisoptional,you'llgetbombardedwithwarningsifyoudon'tspecifyit.Currently,youshouldsetitscontentto9,whichcanbedonebythefollowingsingle-linecommand:

echo9>debian/compat

WecangeneratethebinaryDEBpackagenow.The-ucargumentstandsforuncheckwhile-usstandsforunsign.IfyouhaveaPKGkey,youmayneedtosignthepackagesothatuserscantrustthepackagesyou'vereleased.Wedon'tneedsourcepackages,sothelastargument,-b,indicatesthatonlythebinarypackageswillbebuilt.

dpkg-buildpackage-uc-us-b

Theautomaticallydetecteddependenciescanbeviewedinthedebian/file,internationalization.substvars.Thisfile'scontentsarepastedhere:

shlibs:Depends=libc6(>=2.13-28),libc6(>=2.4),libgcc1(>=

1:4.4.0),libqt5core5a(>=5.0.2),libqt5gui5(>=5.0.2),

libqt5widgets5(>=5.0.2),libstdc++6(>=4.3.0)

misc:Depends=

Aswediscussedearlier,thedependenciesaregeneratedbyshlibsandmisc.Thebiggestadvantageisthatthesegeneratedversionnumberstendtobethesmallest,whichmeansthemaximumbackwardscompatibility.Asyoucansee,ourInternationalizationexamplecanrunonQt5.0.2.

Page 237: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

Ifeverythinggoeswell,you'dexpectaDEBfileinanupper-leveldirectory.However,youcanonlybuildthecurrentarchitecture'sbinarypackage,amd64.Ifyouwanttobuildfori386natively,youneedtoinstalla32-bitx86Debian.Forcross-compilation,refertohttps://wiki.debian.org/CrossBuildPackagingGuidelinesandhttps://wiki.ubuntu.com/CrossBuilding.

InstallingalocalDEBfileiseasilydonewiththefollowingsingle-linecommand:

sudodpkg-iinternationalization_1.0.0-1_amd64.deb

Afterinstallation,wecanrunourapplicationbyrunning/opt/internationalization_demo/Internationalization.ItshouldrunasexpectedandbehaveexactlythesameasonWindows,asshowninthefollowingscreenshot:

Page 238: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

DeployingQtapplicationsonAndroidTheinternationalizationapplicationrequiresaQMfiletobeloadedcorrectly.OnWindowsandLinux,wechoosetoinstallthemalongsidethetargetexecutable.However,thisisnotalwaysagoodapproach,especiallyonAndroid.Thepathismorecomplicatedthanthedesktopoperatingsystems.Besides,we'rebuildingaQtapplicationinsteadoftheJavaapplication.LocalizationisdefinitelydifferentfromaplainJavaapplication,asstatedintheAndroiddocumentation.Hence,we'regoingtobundlealltheresourcesintotheqrcfile,whichwillbebuiltintothebinarytarget:

1. Addanewfiletoprojectbyright-clickingontheproject,andthenselectAddNew….

2. NavigatetoQt|QtResourceFileintheNewFiledialog.3. NameitresandclickonOK;QtCreatorwillredirectyoutoeditres.qrc.4. NavigatetoAdd|AddPrefixandchangePrefixto/.5. NavigatetoAdd|AddFilesandselectthe.Internationalization_de.qmfilein

thedialog.

Now,weneedtoeditmainwindow.cpptomakeitloadthetranslationfilefromResources.WeonlyneedtochangetheconstructorofMainWindowwhereweloadthetranslation,asshownhere:

MainWindow::MainWindow(QWidget*parent):

QMainWindow(parent),

ui(newUi::MainWindow)

{

ui->setupUi(this);

deTranslator=newQTranslator(this);

deTranslator->load(QLocale::German,"Internationalization",

"_",":/");

deLoaded=false;

connect(ui->openButton,&QPushButton::clicked,this,

&MainWindow::onOpenButtonClicked);

connect(ui->loadButton,&QPushButton::clicked,this,

&MainWindow::onLoadButtonClicked);

}

TheprecedingcodeistospecifythedirectoryfortheQTranslator::loadfunction.Aswementionedinthepreviouschapter,:/indicatesthatit'saqrcpath.Don'taddaqrcprefixunlessit'saQUrlobject.

Wecanremovetheqmfileinstallsetfromtheprojectfilenow,becausewe'vealreadybundledtheQMfile.Inotherwords,afterthischange,youdon'tneedtoship

Page 239: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

theQMfileonWindowsorLinuxanymore.Edittheprojectfile,Internationalization.pro,asshowninthefollowingcode:

QT+=coregui

greaterThan(QT_MAJOR_VERSION,4):QT+=widgets

TARGET=Internationalization

TEMPLATE=app

SOURCES+=main.cpp\

mainwindow.cpp

HEADERS+=mainwindow.h

FORMS+=mainwindow.ui

TRANSLATIONS=Internationalization_de.ts

unix:{

target.path=/opt/internationalization_demo

INSTALLS+=target

}

RESOURCES+=\

res.qrc

Now,switchtoProjectsmodeandaddtheAndroidkit.Don'tforgettoswitchthebuildtorelease.InProjectsmode,youcanmodifyhowQtCreatorshouldbuildtheAndroidAPKpackage.ThereisanentryinBuildStepscalledBuildAndroidAPK,asshowninthefollowingscreenshot:

Page 240: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

Here,youcanspecifytheAndroidAPIlevelandyourcertificate.Bydefault,QtDeploymentissettoBundleQtlibrariesinAPK,whichcreatesaredistributableAPKfile.Let'sclickontheCreateTemplatesbuttontogenerateamanifestfile,AndroidManifest.xml.Normally,youjustclickontheFinishbuttononthepop-updialog,andthenQtCreatorwillredirectyoubacktotheEditmodewithAndroidManifest.xmlopenintheeditingarea,asshownhere:

Page 241: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

Let'smakeafewchangestothismanifestfilebyperformingthefollowingsteps:

1. ChangePackagenametocom.demo.internationalization.2. ChangeMinimumrequiredSDKtoAPI14:Android4.0,4.0.1,4.0.2.3. ChangeTargetSDKtoAPI19:Android4.4.4. Savethechanges.

DifferentAPIlevelshaveanimpactoncompatibilityandtheUI;youhavetodecidethelevelscarefully.Inthiscase,werequireatleastAndroid4.0torunthisapplication,whichwe'regoingtoitforAndroid4.4.Generallyspeaking,thehighertheAPIlevel,thebettertheoverallperformanceis.TheInternationalization.proprojectfileisautomaticallychangedaswell.

QT+=coregui

greaterThan(QT_MAJOR_VERSION,4):QT+=widgets

TARGET=Internationalization

TEMPLATE=app

SOURCES+=main.cpp\

mainwindow.cpp

HEADERS+=mainwindow.h

FORMS+=mainwindow.ui

TRANSLATIONS=Internationalization_de.ts

Page 242: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

unix:{

target.path=/opt/internationalization_demo

INSTALLS+=target

}

RESOURCES+=\

res.qrc

DISTFILES+=\

android/gradle/wrapper/gradle-wrapper.jar\

android/AndroidManifest.xml\

android/res/values/libs.xml\

android/build.gradle\

android/gradle/wrapper/gradle-wrapper.properties\

android/gradlew\

android/gradlew.bat

ANDROID_PACKAGE_SOURCE_DIR=$$PWD/android

Now,buildareleasebuild.TheAPKfileiscreatedinandroid-build/bininsidetheprojectbuilddirectory.TheAPKfilenameisQtApp-release.apkorQtApp-debug.apkifyoudon'tsetyourcertificate.Ifyou'regoingtosubmityourapplicationtoGooglePlayoranyotherAndroidmarkets,youhavetosetyourcertificateanduploadQtApp-release.apkinsteadofQtApp-debug.apk.Meanwhile,QtApp-debug.apkcanbeusedonyourowndevicestotestthefunctionalityofyourapplication.

ThescreenshotofInternationalizationrunningonHTCOneisshownasfollows:

Page 243: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount
Page 244: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

Asyoucansee,theGermantranslationisloadedasexpected,whilethepop-updialoghasanativelookandfeel.

Page 245: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

SummaryInthischapter,wecomparedtheadvantagesanddisadvantagesofstaticanddynamiclinking.Lateron,weusedanexampleapplication,showingyouhowtocreateaninstalleronWindowsandhowtopackageitasaDEBpackageonDebianLinux.Lastbutnotleast,wealsolearnedhowtocreatearedistributableAPKfileforAndroid.Theslogan,codeless,createmore,deployeverywhereisnowfulfilled.

Inthenextchapter,whichisalsothelastchapterofthisbook,inadditiontohowtodebugapplications,we'realsogoingtolookatsomecommonissuesandsolutionstothem.

Page 246: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

Chapter10.Don'tPanicWhenYouEncounterTheseIssuesDuringapplicationdevelopment,youmaygetstuckwithsomeissues.Qtisamazing,asalways,sinceQtCreatorhasanexcellentDebugmodethatcansaveyoutimewhendebugging.You'lllearnhowtodebugeitherQt/C++orQtQuick/QMLapplications.Thefollowingtopicswillbecoveredinthischapter:

CommonlyencounteredissuesDebuggingQtapplicationsDebuggingQtQuickapplicationsUsefulresources

CommonlyencounteredissuesErrors,ormoreappropriately,unexpectedresults,aredefinitelyunavoidableduringapplicationdevelopment.Besides,therecouldalsobecompilererrors,orevenapplicationcrashes.Pleasedon'tpanicwhenyouencounterthesekindsofissues.Toeaseyourpainandhelpyoulocatetheproblem,wehavecollectedsomecommonlyencounteredandreproducibleunexpectedresultsandcategorizedthem,asshowninthenextsections.

C++syntaxmistakesForprogrammingbeginners,ordeveloperswhoarenotfamiliarwithCandC++,thesyntaxofC++isnoteasytoremember.Ifthereareanysyntaxmistakes,thecompilerwillabortwitherrormessages.Infact,theeditorwilldisplaytildesbelowproblematicstatements,asshownhere:

Page 247: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

AmongallC++syntaxmistakes,themostcommononeisamissingsemicolon(;).C++needsasemicolontomarktheendofastatement.Therefore,line7andline8areequivalenttothefollowingline:

MainWindowww.show();

This,inC++,isobviouslywrittenincorrectly.Notonlywilltheeditorhighlighttheerror,thecompilerwillalsogiveyouathorougherrormessage.Inthiscase,it'lldisplaythefollowingmessage:

C:\Users\Symeon\OneDrive\Book_Dev\4615OS\4615OS_07\project\Weather_Demo\main.cpp:8:

error:C2146:syntaxerror:missing';'beforeidentifier'w'

Asyoucantell,thecompilerwon'ttellyouthatyoushouldaddasemicolonattheendofline7.Instead,itreadsmissing;beforethewidentifier,whichisinline8.Anyway,inmostcasestheC++syntaxerrorscanbedetectedbythecompiler,whilemostofthemwillfirstbedetectedbytheeditor.ThankstothehighlightingfeatureofQtCreator,thesetypesofmistakesshouldbeavoidedeffectively.

It'srecommendedasagoodhabitthatyouaddasemicolonbeforeyoupressEnter.ThisisbecauseinsomecasesthesyntaxmayseemcorrectforcompilersandQtCreator,butit'sdefinitelywronglycodedandwillcauseunexpectedbehavior.

PointerandmemoryAnyonefamiliarwithCanditswildpointersunderstandshoweasyitistomakeamistakeregardingmemorymanagement.Aswementionedbefore,Qthasasuperiormemorymanagementmechanism,whichwillreleaseitschildobjectsoncetheparentisdeleted.This,unfortunately,mayleadtoacrashifthedeveloperexplicitlyusesdeletetoreleaseachildobject.

Page 248: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

Theprimaryreasonbehindthisisthatdeleteisnotathread-safeoperation.Itmaycauseadoubledelete,resultinginasegmentfault.Therefore,toreleasememoryinathread-safeway,weusethedeleteLater()functiondefinedintheQObjectclass,whichmeansthatthismethodisavailableforallclassesinheritedfromQObject.Asstatedinthedocumentation,deleteLater()willscheduletheobjectfordeletionbutthedeletionwon'thappenimmediately.

NoteIt'scompletelysafetocalldeleteLater()multipletimes.Oncethefirstdeferreddeletioniscompleted,anypendingdeletionsareremovedfromtheeventqueue.Therewon'tbeanydoubledeletes.

ThereisanotherclassdealingwithmemorymanagementinQt,QObjectCleanupHandler.ThisclasswatchesthelifetimeofmultipleQObjects.YoucantreatitasasimpleQtgarbagecollector.Forinstance,therearealotofQTcpSocketobjectsthatneedtobewatchedanddeletedproperly.Thesekindsofcasesarenotuncommon,especiallyfornetworkingprograms.AneasytrickistoaddalltheseobjectstoQObjectCleanupHandler.ThefollowingpieceofcodeisasimpledemonstrationthataddsQObjecttoQObjectCleanupHandlerch:

QTcpSocket*t=newQTcpSocket(this);

QObjectCleanupHandlerch;

ch.add(t);

Addingthetobjecttochwon'tchangetheparentobjectoftfromthisto&ch.QObjectCleanupHandlerismorelikeQListinthisway.Iftisdeletedsomewhereelse,it'llgetremovedfromthelistofchautomatically.Ifthereisnoobjectleft,theisEmpty()functionwillreturntrue.AllobjectsinQObjectCleanupHandlerwillbedeletedwhenit'sdestroyed.Youcanalsoexplicitlycallclear()todeleteallobjectsinQObjectCleanupHandlermanually.

IncompatiblesharedlibrariesThistypeoferrorsaretheso-calledDLLHell,whichwediscussedinthepreviouschapter.Itresultsfromincompatiblesharedlibraries,whichmayleadtostrangebehaviororcrashes.

Inmostcases,Qtlibrariesarebackwardscompatible,whichmeansthatyoumayreplaceallDLLswithneweronesandnotneedtorecompileexecutables.SomecertainmodulesorAPIsmaybedeprecatedandbedeletedfromalaterversionof

Page 249: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

Qt.Forexample,theQGLWidgetclassisreplacedbyanewlyintroducedQOpenGLWidgetclassinQt5.4.QGLWidgetisstillprovidedfornowthough.

Inthereversedirection,thingsaregettingprettybad.IfyourapplicationcallsanAPIthatisintroducedsince,forexample,Qt5.4,theapplicationdefinitelywillmalfunctionwithanolderversionofQt,suchasQt5.2.

ThefollowingisasimpleprogramthatmakesuseofQSysInfo,whichisintroducedinQt5.4.Themain.cppfileofthissimpleincompat_demoprojectisshownhere:

#include<QDebug>

#include<QSysInfo>

#include<QCoreApplication>

intmain(intargc,char*argv[])

{

QCoreApplicationa(argc,argv);

qDebug()<<"CPU:"<<QSysInfo::currentCpuArchitecture();

returna.exec();

}

QSysInfo::currentCpuArchitecture()returnsthearchitectureoftheCPUthattheapplicationisrunningonasaQStringobject.IftheversionofQtishighenough(greaterthanorequalto5.4),it'llrunasexpected,asshowninthefollowingscreenshot:

Page 250: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

Asyoucansee,itsayswe'rerunningthisapplicationona64-bitx86CPUmachine.However,ifweputthecompiledexecutablewithDLLsfromQt5.2,it'llgiveanerrorasshownhereandcrash:

Thissituationisrare,ofcourse.However,ifthishappens,you'llgetanideaaboutwhatgoeswrong.Fromtheerrordialog,wecanseetheerrorisbecauseofthemissingQSysInfo::currentCpuArchitecturelineinthedynamiclinklibrary.

AnotherDLLHellismorecomplexandmaybeignoredbybeginners.Alllibrariesmustbebuiltbythesamecompiler.Youcan'tusetheMSVClibrarieswithGCC,whichholdstrueforothercompilers,suchasICCandClang.Differentcompilerversionsmightcauseincompatibilityaswell.Youprobablydon'twanttousealibrarycompiledbyGCC4.3inyourdevelopmentenvironmentwheretheGCCversionis4.9.However,librariescompiledbyGCC4.9.1shouldbecompatiblewiththosecompiledbyGCC4.9.2.

Inadditiontocompilers,differentarchitecturesareoftenincompatible.Forexample,64-bitlibrarieswon'tworkon32-bitplatforms.Similarly,x86librariesandbinariescan'tbeusedonthenon-x86devices,suchasARMandMIPS.

Doesn'trunonAndroid!QtwasportedtoAndroidnottoolongago.Hence,thereisapossibilitythatitrunswellonadesktopPCbutnotonAndroid.Ononehand,Androidhardwarevaries,notevenspeakingofthousandsofcustomizedROMs.Therefore,itisreasonablethatsomeAndroiddevicesmayencountercompatibilityissues.Ontheotherhand,theQtapplicationrunningonAndroidisanativeC++applicationwithaJavawrapper,whilebinaryexecutablesarenaturallymorevulnerabletocompatibilityissuesthanscripts.

Anyway,here'stherecipe:

1. TrytorunyourapplicationonanotherAndroidhandsetorvirtualAndroiddevice.2. Ifitstilldoesn'twork,itcanbeapotentialbugofQtonAndroid.We'lltalkabout

howtoreportabugtoQtattheendofthischapter.

Page 251: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

DebuggingQtapplicationsTodebuganyQtapplication,youneedtoensurethatyouhaveinstalledthedebugsymbolsoftheQtlibraries.OnWindows,theyareinstalledtogetherwithreleaseversionDLLs.Meanwhile,onLinux,youmayneedtoinstalldebugsymbolsbythedistribution'spackagemanager.

Somedeveloperstendtouseafunctionsimilartoprintftodebugtheapplication.Qtprovidesfourglobalfunctions,whichareshowninthefollowingtable,toprintoutdebug,warnings,anderrortext:

Function Usage

qDebug() Thisfunctionisusedforwritingcustomdebugoutput.

qWarning() Thisfunctionisusedforreportingwarningsandrecoverableerrors.

qCritical()Thisfunctionisusedforwritingcriticalerrormessagesandreportingsystemerrors.

qFatal()Thisfunctionisusedforprintingfatalerrormessagesshortlybeforeexiting.

Normally,youcanjustuseaC-stylemethodsimilartoprintf.

qDebug("Hello%s","World!");

However,inmostcases,we'llincludethe<QtDebug>headerfilesothatwecanusethestreamoperator(<<)asamoreconvenientway.

qDebug()<<"HelloWorld!"

Themostpowerfulplaceofthesefunctionsisthattheycanoutputthecontentsofsomecomplexclasses',QListandQMap.It'snotedthatthesecomplexdatatypescan

Page 252: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

onlybeprintedthroughastreamoperator(<<).

BothqDebug()andqWarning()aredebuggingtools,whichmeanthattheycanbedisabledatcompiletimebydefiningQT_NO_DEBUG_OUTPUTandQT_NO_WARNING_OUTPUT,respectively.

Inadditiontothesefunctions,QtalsoprovidestheQObject::dumpObjectTree()andQObject::dumpObjectInfo()functionswhichareoftenuseful,especiallywhenanapplicationlooksstrange.QObject::dumpObjectTree()dumpsinformationaboutsignalconnections,whichisreallyusefulifyouthinktheremaybeaprobleminsignalslotconnections.Meanwhile,thelatterdumpsatreeofchildrentothedebugoutput.Don'tforgettobuildtheapplicationinDebugmode,otherwiseneitherofthemwillprintanything.

Apartfromtheseusefuldebuggingfunctions,QtCreatorhasofferedanintuitivewaytodebugyourapplication.Ensurethatyou'veinstalledMicrosoftConsoledebugger(CDB)ifyou'reusinganMSVCcompiler.Inothercases,theGDBdebuggerisbundledinaMinGWversion.

NoteCDBisnowapartofWindowsDriverKit(WDK);visithttp://msdn.microsoft.com/en-us/windows/hardware/hh852365todownloadit.Don'tforgettocheckDebuggingToolsforWindowsduringtheinstallation.

ConsiderFancy_ClockfromChapter2,BuildingaBeautifulCross-platformClock,asanexample.IntheMainWindow::setColour()function,movethecursortoline97,whichisswitch(i){.Then,navigatetoDebug|ToggleBreakpointorjustpressF9onthekeyboard.Thiswilladdabreakpointonline97,whichwilladdabreakpointmarker(aredpauseiconinfrontofalinenumber)asshownhere:

Page 253: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

NowclickontheStartDebuggingbuttononthepane,whichhasabugonit,ornavigatetoDebug|StartDebugging|StartDebuggingonthemenubar,orpressF5onthekeyboard.Thiswillrecompiletheapplication,ifneeded,andstartitinDebugmode.Atthesametime,QtCreatorwillautomaticallyswitchtoDebugmode.

Theapplicationisinterruptedbecauseofthebreakpointweset.Youcanseeayellowarrowindicatingwhichlinetheapplicationiscurrentlyon,asshownintheprecedingscreenshot.Bydefault,ontherightpane,youcanseeLocalsandExpressionswhereallthelocalvariablesalongwiththeirvaluesandtypesareshown.Tochangethedefaultsettings,navigatetoWindow|Views,andthenchoosewhattodisplayorhide.

ThepanesintheDebugmodearemarkedinbluetextinthisscreenshot:

Page 254: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

Brieflysaid,youcanmonitorthevariablesinLocalsandexpressionsinExpressions.StackdisplaysthecurrentstackandallbreakpointscanbemanagedintheBreakpointspane.

Onthebottompane,thereareaseriesofbuttonstocontrolthedebuggingprocess.ThefirstsixbuttonsareContinue,StopDebugger,StepOver,StepInto,StepOut,andRestartthedebuggingsession,respectively.StepOveristoexecutealineofcodeasawhole.StepIntowillstepintoafunctionorasubfunction,whileStepOutcanleavethecurrentfunctionorsubfunction.

Breakpointsplaysacrucialroleindebugging,asyoucantellwhetherabreakpointrepresentsapositionorsetofpositionsinthecodethatinterruptstheapplicationfrombeingdebuggedandgrantsyoucontrol.Onceitisinterrupted,youcanexaminethestateoftheprogramorcontinuetheexecution,eitherline-by-lineorcontinuously.QtCreatorshowsbreakpointsintheBreakpointsview,whichislocatedatthelower-right-handsidebydefault.YoucanaddordeletebreakpointsintheBreakpointsview.Toaddabreakpoint,right-clickontheBreakpointsviewandselectAddBreakpoint…;therewillbeanAddBreakpointdialogasshownhere:

Page 255: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

IntheBreakpointtypefield,selectthelocationintheprogramcodewhereyouwanttheapplicationtobeinterrupted.Otheroptionsaredependentontheselectedtype.

Tomovethebreakpoint,simplydragthebreakpointmarkeranddropitonthedestination.It'snotanoftenneededfunction,though.

There'remanywaystodeleteabreakpoint.

Byclickingonthebreakpointmarkerintheeditor,movingthecursortothecorrespondingline,andnavigatingtoDebug|ToggleBreakpoint,orbypressingF9Byright-clickingonthebreakpointintheBreakpointsviewandselectingDeleteBreakpointByselectingthebreakpointintheBreakpointsviewandpressingtheDeletebuttononthekeyboard

ThemostpowerfulplaceisthepreviouslyintroducedLocalsandExpressionsview.Everytimetheprogramstopsunderthecontrolofthedebugger,itretrievesinformationanddisplaysitintheLocalsandExpressionsview.TheLocalspaneshowsfunctionparametersandlocalvariables.Thereisacomprehensivedisplayof

Page 256: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

databelongingtoQt'sbasicobjects.Inthiscase,whentheprogramisinterruptedinMainWindow::setColour(),thereisapointerwhoseValueis"MainWindow".Insteadofjustmemoryaddressofthispointer,itcanshowyouallthedataandchildrenthatbelongtothisobject:

Asyoucanseefromprecedingscreenshot,thisisaMainWindowinstance,whichisinheritedfromQMainWindow.Ithasthreechildrenitems:_layout,qt_rubberband,andcentralWidget.It'snotedthatonlyslotfunctionsaredisplayedin[methods].Nowyou'llunderstandwhytheLocalspaneisthemostimportantandcommonlyusedviewintheDebugmode.

Ontheotherhand,theExpressionspaneisevenmorepowerfulandcancomputethevaluesofarithmeticexpressionsorfunctioncalls.Right-clickontheLocalsandExpressionsviewandselectAddNewExpressionEvaluator…inthecontextmenu.

Page 257: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

Notethatthecontextmenuentriesareavailableonlywhentheprogramisinterrupted.Inthiscase,Fancy_ClockisinterruptedintheMainWindow::setColour()functionwherethelocalvariable,i,canbeusedtoperformsomearithmeticoperations.Forexample,wefilli*5intheNewEvaluatedExpressionpop-updialog.

Inadditiontoarithmeticoperations,youcancallafunctiontoevaluatethereturnvalue.However,thisfunctionmustbeaccessibletothedebugger,whichmeansit'seithercompiledintotheexecutableorcanbeinvokedfromalibrary.

Theexpressionvaluewillbere-evaluatedaftereachstep.AfteryouclickontheOKbutton,theexpressioni*5,isshownintheExpressionspaneasshownhere:

Thevalueofiisnow3.Therefore,theexpressioni*5isevaluatedas15.

"Expressionevaluatorsarepowerful,butslowdowndebuggeroperationsignificantly.Itisadvisablenottousethemexcessively,andtoremoveunneeded

expressionevaluatorsassoonaspossible."

Eveniffunctionsusedintheexpressionshavesideeffects,theywillbecalledeachtimethecurrentframechanges.Afterall,theexpressionevaluatorispowerfulbutbadfordebuggingspeed.

Page 258: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

DebuggingQtQuickapplicationsWewillusetheWeather_QMLprojectfromChapter7,ParsingJSONandXMLDocumentstoUseOnlineAPIs,asademonstrationprogramtoshowhowtodebugaQtQuickapplication.

First,weneedtoensurethatQMLdebuggingisenabled.OpentheWeather_QMLprojectinQtCreator.Then,performthefollowingsteps:

1. SwitchtotheProjectsmode.2. ExpandtheqmakestepinBuildSteps.3. CheckEnableQMLdebuggingifit'snotchecked.

TipDebuggingQMLwillopenasocketatawell-knownport,whichposesasecurityrisk.AnyoneonyournetworkcouldconnecttothedebuggingapplicationandexecuteanyJavaScriptfunction.Therefore,youhavetomakesurethereareappropriatefirewallrules.

ThesameprocedureisusedtostartQMLdebugging,whichistonavigatetoDebug|StartDebugging|StartDebugging,orclicktheDebugbutton,orjustpressF5.ItmaytriggeraWindowsSecurityAlert,showninthefollowingscreenshot.Don'tforgettoclickontheAllowaccessbutton.

Page 259: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

Oncetheapplicationstartsrunning,itbehavesandperformsasusual.However,youcanperformsomeusefultasksindebuggingmode.YoucanseealltheelementsandtheirpropertiesintheLocalspaneaswedidfortheQt/C++applications.

Inadditiontojustwatchingthesevariables,youcanchangethemtemporarilyandseethechangesatruntimeimmediately.Tochangeavalue,youcaneitherdirectlychangeitintheLocalspaneorchangeitinQML/JSConsole.

Forexample,tochangethetitlepropertyofApplicationWindow,performthefollowingsteps:

1. ExpandApplicationWindow|PropertiesintheLocalspane.2. Double-clickonthetitleentry.3. ChangethevaluefromWeatherQMLtoYahoo!Weather.4. PresstheEnterorReturnkeyonthekeyboardtoconfirm.

Alternatively,youcanchangeitinQML/JSConsole.ThereisnoneedtoexpandApplicationWindow;justclickonApplicationWindowintheLocalspane.You'llnoticeContextontheQML/JSConsolepanelwillbecomeApplicationWindow,asshowninthefollowingscreenshot.Then,justinputthetitle="Yahoo!Weather"commandtochangethetitle.

Page 260: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

You'llnoticethetitleintheapplicationwindowischangedtoYahoo!Weatherimmediately,asshownhere:

Meanwhile,thesourcecodeisleftintact.Thisfeatureisreallyhandywhenyouwanttotestabettervalueforaproperty.Insteadofchangingitinthecodeandrerunning,youcanchangeandtestitonthefly.Infact,youcanalsoexecutetheJavaScriptexpressionsinQML/JSConsole,notjustchangetheirvalues.

Page 261: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

UsefulresourcesStillgettingstuckwithanissue?Inadditiontoonlinesearchengines,therearetwoonlineforumsthatcouldalsobeusefulforyou.ThefirstoneistheforumintheQtProject,whoseURLishttp://qt-project.org/forums.Theotheroneismaintainedbyacommunitysite,QtCentre,anditsURLishttp://www.qtcentre.org/forum.php.

Inmostcases,youshouldbeabletofindsimilarorevenidenticalproblemsonthesewebsites.Ifnot,youcanpostanewthreadaskingforhelp.Describetheproblemasthoroughlyaspossiblesothatotheruserscangetanideaofwhat'sgoingwrong.

Thereisapossibilitythatyoudideverythingcorrectlybutstillmightbegettingunexpectedresults,compilererrors,orcrashes.Inthiscase,itmaybeaQtbug.Ifyoubelievethatyou'veencounteredaQtbug,youareencouragedtoreportit.It'seasytoreportabugsinceQthasabugtracker,whoseURLishttps://bugreports.qt.io.

TipThequalityofthebugreportdramaticallyimpactshowsoonthebugwillbefixed.

Toproduceahigh-qualitybugreport,hereisasimplestep-by-stepmanual:

1. VisittheQtbugtrackerwebsite.2. Login.Ifit'syourfirsttime,youneedtocreateanewaccount.Rememberto

supplyavalide-mailaddressasthisistheonlywayfortheQtdeveloperstocontactyou.

3. UsetheSearchfieldontheupper-rightsidetofindanysimilar,orevenidenticalbugs.

4. Ifyoufindone,youcanleaveacommentwithanyadditionalinformationthatyouhave.Besides,youcanclickonVotetovoteforthatbug.Lastly,youcouldaddyourselfasawatcherifyouwanttotracktheprogress.

5. Ifnot,clickonCreateNewIssuesandfillinthefields.

YoushouldenterabriefdescriptivetextinSummary.Thisisnotonlyforahigherchancetogetitfixed,butalsogoodforotherpeoplesearchingforexistingbugs.Forotherfields,you'realwaysencouragedtoprovideasmuchinformationasyoucan.

Page 262: Table of Contentsread.pudn.com/downloads767/ebook/3045877/Qt 5 Blueprints.pdfTable of Contents Qt 5 Blueprints Credits About the Author About the Reviewers Support files, eBooks, discount

SummaryAfterhavingareadthroughthischapter,youcansortoutthemajorityofQt-basedissuesonyourown.Westartedoffwithafewcommonlyencounteredproblems,followedbyhowtodebugQtandQtQuickapplications.Attheend,therewereafewusefullinkstohelpyoucrackdownonthevariedissuesanderrors.IfyouencounteranyproblemwithaparticularQtbug,don'tpanic,justgotothebugtrackerandreportit.