/
flow.py
387 lines (337 loc) · 13.6 KB
/
flow.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
# -*- coding: utf-8 -*-
"""
flow.py
-------
flow.py is the applications starting execution starting point, thus
the name flow is appropriate.
"""
# Python stdlib imports
import os
import shutil
import sqlite3
import sys
# PySide module imports
from PySide.QtGui import QApplication, QMainWindow, QDialog, QFileDialog, \
QDialogButtonBox, QTableWidgetItem
# UI Design module imports
from FluiDevUI import *
from NewWebsiteDialogUI import *
class FluiDevWebsite(object):
"""
TODO
"""
def __init__(self, website_name, website_path, date_created, date_edited):
"""
TODO
"""
super(FluiDevWebsite, self).__init__()
self.website_name = website_name
self.website_path = website_path
self.date_created = date_created
self.date_edited = date_edited
@staticmethod
def create(conn, website_name, website_path, date_created, date_edited):
cursor = conn.cursor()
query = """INSERT INTO FluiDevWebsite VALUES(
NULL, :website_name, :website_path, :date_created, :date_edited
)"""
cursor.execute(
query,
{
'website_name': website_name,
'website_path': website_name,
'date_created': date_created,
'date_edited': date_edited
}
)
cursor.close()
@staticmethod
def read(conn, column_names, table_name):
"""
TODO
"""
fd_websites = list()
cursor = conn.cursor()
query = "SELECT %s FROM %s" % (column_names, table_name)
cursor.execute(query)
read_data = cursor.fetchall()
cursor.close()
for row in read_data:
fd_websites.append(FluiDevWebsite(row[0], row[1], row[2], row[3]))
return fd_websites
@staticmethod
def update(conn):
pass
@staticmethod
def delete(conn):
#cursor = conn.cursor()
#query = "DELETE FROM FluiDevWebsite"
# DELETE FROM `table_name` ??? WHERE clause ???
cursor.close()
pass
class NewWebsiteDialog(QDialog):
"""
NewWebsiteDialog is a QDialog window that implements what happens if
the user decides to click the `Create a New Website` button.
This class sets up the UI and functionality for the QDialog that
aims at making the creation of a new project simple.
"""
def __init__(self, parent=None):
"""
Initializes the NewWebsiteDialog QDialog window by creating some
class bound variables, setting up the UI, and connecting signals
and slots.
self.website_name - This variable stores the website name that
is typed in by the user.
self.website_containing_path - This variable holds the path that
the user chooses. This path will hold a directory named after
`self.website_name`.
self.full_website_path - This variable holds the full path of
the new website. This includes `self.website_containing_path`
and `self.website_name`.
self.new_website_skeleton_path - This variable holds the full
path of the new website skeleton. The contents of this directory
will be copied into every new website the user creates.
Three signals are connected to slots that handle input for a new
website name, website path, and whether the user will create it
via the `Ok` button or not via the `Cancel` button.
"""
super(NewWebsiteDialog, self).__init__(parent)
self.website_name = ''
self.website_containing_path = ''
self.full_website_path = ''
self.website_skeleton_path = os.getcwd() + '/assets/skeleton'
self.showing_warning = False
self.ui = NewWebsiteDialogUIDesign()
self.ui.setupUi(self)
self.ui.chooseLocationButton.setDisabled(True)
self.ui.okCancelButtonBox.button(QDialogButtonBox.Ok).setDisabled(True)
self.ui.websiteNameTextField.textChanged.connect(
self.nameOfWebsiteChanged
)
self.ui.okCancelButtonBox.accepted.connect(self.createNewWebsite)
self.ui.chooseLocationButton.clicked.connect(
self.chooseWebsiteLocation
)
def nameOfWebsiteChanged(self):
"""
nameOfWebsiteChanged is executed when the user makes a change to
the text in the `Website Name`.
self.website_name - this variable holds the value used for the
new websites name.
This function checks sets the name of the website that will be
used to create a directory with the same name in the file system
of the computer. While setting this value it also checks whether
the path has already been chosen it also makes sure that if the
path is picked and the websites name changes it updates the path
automatically. Another thing it does is handle whether the `Ok`
button and `Choose Location` button are enabled and disabled in
the correct manner.
For example if the user has not typed a name in the `Website
Name` box then both the `Choose Location` and the `Ok` button
are disabled. When the user enters the website name the `Choose
Location` button becomes enabled. After the user has chosen a
location to store their site at the `Ok` button becomes enabled.
Now the user can either click ok and the website is created,
change the path of the website, or change the name. If the name
is changed the path is updated in real time as stated above.
"""
self.website_name = self.ui.websiteNameTextField.text()
if self.ui.locationTextField.text():
self.full_website_path = (
self.website_containing_path +
'/' +
self.website_name
)
self.ui.locationTextField.setText(self.full_website_path)
self.existingDirectoryCheck()
choose_location_enabled = self.ui.chooseLocationButton.isEnabled()
if choose_location_enabled and not self.website_name:
self.ui.chooseLocationButton.setEnabled(False)
self.ui.okCancelButtonBox.button(QDialogButtonBox.Ok).setEnabled(
False
)
self.hideWarningLabels()
elif not choose_location_enabled:
self.ui.chooseLocationButton.setEnabled(True)
if self.ui.locationTextField.text():
self.ui.okCancelButtonBox.button(
QDialogButtonBox.Ok).setEnabled(True)
self.ui.okCancelButtonBox.button(
QDialogButtonBox.Ok).setDefault(True)
def chooseWebsiteLocation(self):
"""
chooseWebsiteLocation is executed when the user clicks the
`Choose location...` button.
self.website_containing_path - this variable holds the path that
the user will set using the native file system dialog which is
called by the QFileDialog static method `getExistingDirectory`.
The function does a check to make sure that the path actually
exists then sets the `self.full_website_path`. The read only
QLineEdit text is then set to a string representing the path
chosen + the name of the website. For a greater user experience
the QDialogButtonBox.Ok button is enabled and set as the default
option.
"""
chosen_location = QFileDialog().getExistingDirectory(
self,
"Choose location for website",
"/"
)
if chosen_location:
self.website_containing_path = chosen_location
if self.website_containing_path:
self.full_website_path = (
self.website_containing_path +
'/' +
self.website_name
)
self.existingDirectoryCheck()
self.ui.locationTextField.setText(self.full_website_path)
self.ui.okCancelButtonBox.button(QDialogButtonBox.Ok).setEnabled(
True
)
self.ui.okCancelButtonBox.button(QDialogButtonBox.Ok).setDefault(
True
)
def createNewWebsite(self):
"""
createNewWebsite is executed when a `self.website_name` and
`self.website_containing_path` have been set and the user clicks
the QDialogButtonBox.Ok button.
self.full_website_path - this variable holds the path where the
new websites project directory and files will be created.
When this function is ran a directory by the name of the website
is created at the specified path and some bare bones files and
directories are copied into the website directory. The contents
of the website directory contain the bare minimum that must be
done for most sites while still giving the user complete content
control.
"""
self.full_website_path = (
self.website_containing_path +
'/' +
self.website_name
)
try:
shutil.rmtree(self.full_website_path)
shutil.copytree(self.website_skeleton_path, self.full_website_path)
## Add this website to the list of FluiDevWebsite right here ##
except OSError:
pass
def existingDirectoryCheck(self):
"""
TODO
"""
if os.path.exists(self.full_website_path) and not self.showing_warning:
warning_title = 'Warning:'
warning_message = """Clicking the Ok button will overwrite an
existing folder.
"""
self.showWarningLabels(warning_title, warning_message)
else:
self.hideWarningLabels()
def showWarningLabels(self, warning_title, warning_message):
"""
TODO
"""
self.showing_warning = True
self.ui.warningTitleLabel.setText(warning_title)
self.ui.warningContentLabel.setText(warning_message)
def hideWarningLabels(self):
"""
TODO
"""
self.showing_warning = False
self.ui.warningTitleLabel.clear()
self.ui.warningContentLabel.clear()
class FluiDevWindow(QMainWindow):
"""
FluiDevWindow is a QMainWindow that implements the first window a
user will see when they open FluiDev.
This class initializes the UI design and functionality and from here
one can view FluiDev features, create a new website, and resume work
on existing projects.
"""
def __init__(self, fd_websites, parent=None):
"""
Initializes the FluiDevWindow class by declaring the UI design
and connecting the necessary signals and slots.
self.existing_website_paths - this will hold the apps existing
website paths and will get then be used to create a list of type
FluiDevWebsite.
self.ui - this will hold the QMainWindow object with the design
from FluiDevWindow. After the UI is setup then the `Create a
New Website` button signal is connected to the
`createNewWebsiteButtonPushed` slot.
"""
super(FluiDevWindow, self).__init__(parent)
self.fd_websites = fd_websites
self.ui = FluiDevUIDesign()
self.ui.setupUi(self)
self.populateExistingFluiDevWebsites()
self.ui.createNewWebsiteButton.clicked.connect(
self.createNewWebsiteButtonPushed
)
def populateExistingFluiDevWebsites(self):
"""
TODO
"""
for website in self.fd_websites:
new_row = self.ui.existingWebsitesDisplay.rowCount()
self.ui.existingWebsitesDisplay.insertRow(new_row)
self.ui.existingWebsitesDisplay.setItem(
new_row,
0,
QTableWidgetItem(website.website_name)
)
self.ui.existingWebsitesDisplay.setItem(
new_row,
1,
QTableWidgetItem(website.date_created)
)
self.ui.existingWebsitesDisplay.setItem(
new_row,
2,
QTableWidgetItem(website.date_edited)
)
def createNewWebsiteButtonPushed(self):
"""
createNewWebsiteButtonPushed is executed when the user presses
the `Create a New Website` button.
newWebsiteDialog - creates a QDialog of type NewWesbsitePrompt.
"""
newWebsiteDialog = NewWebsiteDialog()
newWebsiteDialog.show()
newWebsiteDialog.exec_()
def goWithTheFlow():
"""
goWithTheFlow handles all of the necessary aspects of starting the
FluiDev application. This consists of creating/initializing the db,
creating a QApplication, creating the main FluiDevWindow and then
executing the application.
app - QApplication necessary in every PySide application
fluiDevWindow - QMainWindow object that represent the first window
the user will see when they run the application
"""
fd_websites = list()
db_file = 'FluiDev.db'
db_schema_file = 'FluiDevSchema.sql'
db_is_new = not os.path.exists(db_file)
with sqlite3.connect(db_file) as conn:
if db_is_new:
with open(db_schema_file, 'rt') as schema_file:
schema = schema_file.read()
conn.executescript(schema)
fd_websites = FluiDevWebsite.read(
conn,
'website_name, website_path, date_created, date_edited',
'FluiDevWebsite'
)
conn.close()
app = QApplication(sys.argv)
fluiDevWindow = FluiDevWindow(fd_websites)
fluiDevWindow.show()
sys.exit(app.exec_())
if __name__ == "__main__":
goWithTheFlow()