Linux Format - UK (2020-03)

(Antfer) #1
http://www.techradar.com/pro/linux March 2020 LXF260 89

Python & Qt5 CODING ACADEMY


Figure 2: Qt 5
Designer’s New
Form Dialog.
You want to
choose Dialog
without Buttons.

GITSTATUS.PY METHODS


shown in Figure 4.
GitStatusDialog.ui is an XML file. We’re going to use
the pyuic5 tool to convert it to a Python file. At the
command line type:
pyuic5 -x -o gitStatus.py GitStatusDialog.ui.
We’re now going to edit gitStatus.py, so be careful not
to run the previous command again or you’ll overwrite
your Python file.
Before we edit gitStatus.py, let’s see what pyuic5
gave us. At the command line type:
python3 gitStatus.py
You should see the empty dialog. Clicking
pushButtonClose should close the application, since
we’ve already hooked up the signal and slot for that
button. pyuic5 created a working dialog that doesn’t
really do anything.
GitStatus.py should now contain the class
Ui_GitStatus. The class should have two methods:
setupUi(self, gitStatus) and retranslateUi(self, gitStatus).
The -x option in pyuic5 also created a main section for
our project.
Now, you’ll add some functionality to gitStatus.py.
Open up gitStaus.py in your text editor. Add #!/usr/bin/
env python3 as the first line in the program. This tells
Bash that if we ask it to execute gitStatus.py, it will load
Python 3 to do it. In order for that to happen, we need to
set the flag that tells Bash that gitStatus.py is an
executable program. At the command line, type:
chmod +x gitStatus.py
Go back to your editor and add the signals and slots
for pushButtonRefresh, listWidgetRepo and
listWidgetStatus. At the end of the method
retranslateUi(self, GitStatus) add the following lines:
# hook up signals (widget outputs) and slots (class
member methods)
self.listWidgetRepo.itemSelectionChanged.
connect(self.repoSelectionChanged)
self.listWidgetStatus.itemSelectionChanged.
connect(self.statusSelectionChanged)
self.pushButtonRefresh.clicked.connect(self.refresh).
Now add the methods that we want to call when
pushButtonRefresh is clicked or the selection is
changed in listWidgetRepo or listWidgetStatus:
def refresh(self): # pushButtonRefresh has been
clicked
def repoSelectionChanged(self): # listWidgetRepo
selection changed
def statusSelectionChanged(self): # listWidgetStatus
selection changed
Populate these functions by copying the code from
gitStatus.py.original. Continue adding methods to
gitStatus.py. There is a lot of code to copy. If you’re
building gitStatus.py from scratch, open gitStatus.
py.original in your code editor and copy the code from
there. You need to add the methods shown in the boxout
(see right).
The program works by initially searching for git
repositories, determining their default colour (red,
orange or green) by invoking the git status --porcelain
command, populating and then alphabetising
listWidgetRepo. This happens in the method
populateDialog(). We call populateDialog() once in
main(), before the dialog is visible. We also call
populateDialog() when pushButtonRefresh is clicked.
Every time listWidgetRepo’s selected working

directory is changed, and it is changed when we first
populate listWidgetRepo, the selectionChanged()
method is called. That’s where we call git and get all of
the modified, deleted, added, removed or untracked
files in the selected working directory. We determine the
colour for each issue that git status reports, and then
we populate listWidgetStatus with that information.
The first thing we do is to construct a QApplication
object with any options passed to main() on the
command line. This occurs in line 466 of gitStatus.py:
app = Qapplication(sys.argv)
We then set the application’s name and version for the
QCommandLineParser class in lines 467 and 468:
clp = QcommandLineParser()
This handles the --help, --version, and the --verbose
command line options. This is all taken care of for us by
the clp.process(sys.argv) statement in line 476.
We then construct our dialog in line 478:
GitStatus = QtWidgets.Qdialog() # construct QDialog
ui = Ui_GitStatus() # instantiate ui
ui.setupUi(GitStatus) # configure all widgets
ui.isVerbose = clp.isSet(verboseOption)
We now call the parseConfigFile() function to read
gitStatus.ini, which is located in the same directory as
gitStatus.py. If gitStatus.ini is not found,
parseConfigFile() will create gitStatus.ini and make

Methods to be added to gitStatus.py:
hasGitDir(self, dir): returns True if dir has a subdirectory .git.
appendSlash(self, str): appends / to str if str doesn’t end with /.
quickCheckPriority(self, dir): uses git status --porcelain. It returns
COLOR_RED for modified files, COLOR_ORANGE for deleted, added,
copied or untracked files, else COLOR_GREEN.
refresh(self): This is the SLOT for the pushButtonRefresh clicked
signal. It clears and repopulates the dialog.
statusSelectionChanged(self): when listWidgetStatus selection has
changed. Sets a stylesheet for the selected item in listWidgetStatus.
repoSelectionChanged(self): when listWidgetRepo selection has
changed. Sets a stylesheet for the selected item in listWidgetRepo.
Also invokes git status --porcelain to populate listWidgetStatus.
populateDialog(self): fills in all the fields of the dialog. Searches
disk(s) for directories containing git repositories and populates
listWidgetRepo accordingly.
parseConfigFile(self): reads or creates gitStatus.ini and determines
the searched directories and the directories we want to ignore.
main: parses command line options and instantiates, populates and
shows the dialog.

You can run ,
which will create
gitStatus.html. If
you have LAMP
server on your
system, copy
gitStatus.html
to /srv/www/
htdocs and
serve it up using
apache2. Open
a browser and
select localhost/
gitStatus.html
in the address
bar. /srv/
www/htdocs
is the location
apache2 uses to
serve files in our
distro. Search
for htdocs to
find where it is
on your system.

888March 202 Mcdisu dsePyQt March 2020 LXF260 89


Python & Qt5 CODING ACADEMY


Figure 2: Qt 5
Designer’s New
Form Dialog.
You want to
choose Dialog
without Buttons.

GITSTATUS.PY METHODS


shown in Figure 4.
GitStatusDialog.ui is an XML file. We’re going to use
the pyuic5 tool to convert it to a Python file. At the
command line type:
pyuic5 -x -o gitStatus.py GitStatusDialog.ui.
We’re now going to edit gitStatus.py, so be careful not
to run the previous command again or you’ll overwrite
your Python file.
Before we edit gitStatus.py, let’s see what pyuic5
gave us. At the command line type:
python3 gitStatus.py
You should see the empty dialog. Clicking
pushButtonClose should close the application, since
we’ve already hooked up the signal and slot for that
button. pyuic5 created a working dialog that doesn’t
really do anything.
GitStatus.py should now contain the class
Ui_GitStatus. The class should have two methods:
setupUi(self, gitStatus) and retranslateUi(self, gitStatus).
The -x option in pyuic5 also created a main section for
our project.
Now, you’ll add some functionality to gitStatus.py.
Open up gitStaus.py in your text editor. Add #!/usr/bin/
env python3 as the first line in the program. This tells
Bash that if we ask it to execute gitStatus.py, it will load
Python 3 to do it. In order for that to happen, we need to
set the flag that tells Bash that gitStatus.py is an
executable program. At the command line, type:
chmod +x gitStatus.py
Go back to your editor and add the signals and slots
for pushButtonRefresh, listWidgetRepo and
listWidgetStatus. At the end of the method
retranslateUi(self, GitStatus) add the following lines:


hook up signals (widget outputs) and slots (class


member methods)
self.listWidgetRepo.itemSelectionChanged.
connect(self.repoSelectionChanged)
self.listWidgetStatus.itemSelectionChanged.
connect(self.statusSelectionChanged)
self.pushButtonRefresh.clicked.connect(self.refresh).
Now add the methods that we want to call when
pushButtonRefresh is clicked or the selection is
changed in listWidgetRepo or listWidgetStatus:
defrefresh(self):#pushButtonRefreshhasbeen
clicked
defrepoSelectionChanged(self): # listWidgetRepo
selection changed
def statusSelectionChanged(self): # listWidgetStatus
selection changed
Populate these functions by copying the code from
gitStatus.py.original. Continue adding methods to
gitStatus.py. There is a lot of code to copy. If you’re
building gitStatus.py from scratch, open gitStatus.
py.original in your code editor and copy the code from
there. You need to add the methods shown in the boxout
(see right).
The program works by initially searching for git
repositories, determining their default colour (red,
orange or green) by invoking the git status --porcelain
command, populating and then alphabetising
listWidgetRepo. This happens in the method
populateDialog(). We call populateDialog() once in
main(), before the dialog is visible. We also call
populateDialog() when pushButtonRefresh is clicked.
Every time listWidgetRepo’s selected working


directory is changed, and it is changed when we first
populate listWidgetRepo, the selectionChanged()
method is called. That’s where we call git and get all of
the modified, deleted, added, removed or untracked
files in the selected working directory. We determine the
colour for each issue that git status reports, and then
we populate listWidgetStatus with that information.
The first thing we do is to construct a QApplication
object with any options passed to main() on the
command line. This occurs in line 466 of gitStatus.py:
app = Qapplication(sys.argv)
We then set the application’s name and version for the
QCommandLineParser class in lines 467 and 468:
clp = QcommandLineParser()
This handles the --help, --version, and the --verbose
command line options. This is all taken care of for us by
the clp.process(sys.argv) statement in line 476.
We then construct our dialog in line 478:
GitStatus= QtWidgets.Qdialog()#constructQDialog
ui= Ui_GitStatus()# instantiate ui
ui.setupUi(GitStatus) # configure all widgets
ui.isVerbose = clp.isSet(verboseOption)
We now call the parseConfigFile() function to read
gitStatus.ini, which is located in the same directory as
gitStatus.py. If gitStatus.ini is not found,
parseConfigFile() will create gitStatus.ini and make

MethodstobeaddedtogitStatus.py:
hasGitDir(self,dir):returnsTrueifdirhasasubdirectory.git.
appendSlash(self,str):appends/tostrifstrdoesn’tendwith/.
quickCheckPriority(self, dir): uses git status --porcelain. It returns
COLOR_REDformodifiedfiles,COLOR_ORANGEfordeleted,added,
copiedoruntrackedfiles,elseCOLOR_GREEN.
refresh(self):ThisistheSLOTforthepushButtonRefreshclicked
signal.Itclearsandrepopulatesthedialog.
statusSelectionChanged(self):whenlistWidgetStatusselectionhas
changed.SetsastylesheetfortheselectediteminlistWidgetStatus.
repoSelectionChanged(self): when listWidgetRepo selection has
changed.SetsastylesheetfortheselectediteminlistWidgetRepo.
Alsoinvokesgitstatus--porcelaintopopulatelistWidgetStatus.
populateDialog(self): fills in all the fields of the dialog. Searches
disk(s)fordirectoriescontaininggitrepositoriesandpopulates
listWidgetRepoaccordingly.
parseConfigFile(self):readsorcreatesgitStatus.inianddetermines
thesearcheddirectoriesandthedirectorieswewanttoignore.
main: parses command line options and instantiates, populates and
shows the dialog.

Youcanrun,
whichwillcreate
gitStatus.html.If
youhaveLAMP
serveronyour
system,copy
gitStatus.html
to/srv/www/
htdocsand
serveit upusing
apache2.Open
a browserand
selectlocalhost/
gitStatus.html
intheaddress
bar./srv/
www/htdocs
isthelocation
apache2usesto
servefilesinour
distro.Search
forhtdocsto
findwhereit is
onyoursystem.
Free download pdf