-
Notifications
You must be signed in to change notification settings - Fork 2
/
application_gui.py
2287 lines (1999 loc) · 136 KB
/
application_gui.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
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
import os
import webbrowser
import io
# folium v0.12.1 - Used to display geographical data
import folium
import application_database
import application_filter_request
# ipregistry v3.2.0 - Used to find current location of the user when called
from ipregistry import IpregistryClient
from time import gmtime, strftime
from operator import itemgetter
# PyQt5 v5.15.6 - Used to create interface and all visual components.
from PyQt5 import QtCore, QtGui, QtWidgets, QtWebEngineWidgets
# PyQtWebEngine v5.15.5 - Used to display web widgets. Folium maps are displayed using this library.
from PyQt5.QtWebEngineWidgets import QWebEngineView, QWebEngineSettings
# geopy v2.2.0 - Used to calculate distance between two points using latitude and longitude values.
from geopy import distance
from geopy.geocoders import Nominatim
geolocator = Nominatim(user_agent="geoapiExercises")
# Connect to ip finder as a client in order to get information about the ip
global ip_is_found
try:
client = IpregistryClient("72bw4jakulj27ism")
ipInfo = client.lookup()
ip_is_found = True
except:
ip_is_found = False
class CollapsibleBox(QtWidgets.QWidget):
def __init__(self, title="", parent=None):
super(CollapsibleBox, self).__init__(parent)
self.toggle_button = QtWidgets.QToolButton(
text=title, checkable=True, checked=False
)
self.toggle_button.setFixedWidth(758)
# self.toggle_button.setStyleSheet("QToolButton { border: none; }")
self.toggle_button.setToolButtonStyle(
QtCore.Qt.ToolButtonTextBesideIcon
)
self.toggle_button.setArrowType(QtCore.Qt.RightArrow)
self.toggle_button.pressed.connect(self.on_pressed)
self.toggle_animation = QtCore.QParallelAnimationGroup(self)
self.content_area = QtWidgets.QScrollArea(
maximumHeight=0, minimumHeight=0
)
self.content_area.setSizePolicy(
QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed
)
self.content_area.setFrameShape(QtWidgets.QFrame.NoFrame)
lay = QtWidgets.QVBoxLayout(self)
lay.setSpacing(0)
lay.setContentsMargins(0, 0, 0, 0)
lay.addWidget(self.toggle_button)
lay.addWidget(self.content_area)
self.toggle_animation.addAnimation(
QtCore.QPropertyAnimation(self, b"minimumHeight")
)
self.toggle_animation.addAnimation(
QtCore.QPropertyAnimation(self, b"maximumHeight")
)
self.toggle_animation.addAnimation(
QtCore.QPropertyAnimation(self.content_area, b"maximumHeight")
)
@QtCore.pyqtSlot()
def on_pressed(self):
checked = self.toggle_button.isChecked()
self.toggle_button.setArrowType(
QtCore.Qt.DownArrow if not checked else QtCore.Qt.RightArrow
)
self.toggle_animation.setDirection(
QtCore.QAbstractAnimation.Forward
if not checked
else QtCore.QAbstractAnimation.Backward
)
self.toggle_animation.start()
def setContentLayout(self, layout):
lay = self.content_area.layout()
del lay
self.content_area.setLayout(layout)
collapsed_height = (
self.sizeHint().height() - self.content_area.maximumHeight()
)
content_height = layout.sizeHint().height()
for i in range(self.toggle_animation.animationCount()):
animation = self.toggle_animation.animationAt(i)
animation.setDuration(500)
animation.setStartValue(collapsed_height)
animation.setEndValue(collapsed_height + content_height)
content_animation = self.toggle_animation.animationAt(
self.toggle_animation.animationCount() - 1
)
content_animation.setDuration(500)
content_animation.setStartValue(0)
content_animation.setEndValue(content_height)
# Creates an the instance of QApplication, and creates all corresponding class functions
class Ui_MainWindow(object):
global filtered_attractions_list
global radius_checked
radius_checked = False
filtered_attractions_list = []
# Upon being called, this function creates a QLabel associated with a container that is specified by the string
# parameter (container). The QLabel's geometry is specified by the location parameters (x_coordinate, y_coordinate)
# and the size parameters (width, length) passed through the function.
#
# Returns a QLabel object
def create_QLabel(self, container, x_coordinate, y_coordinate, width, length):
global location_and_filters_QGroupBox
global attractions_QGroupBox_bar
global attraction_QScrollArea_object
# Creates and associates QLabel to specified container
if container == "location_and_filters_QGroupBox":
self.QLabel = QtWidgets.QLabel(self.location_and_filters_QGroupBox)
elif container == "attraction_QScrollArea_object":
self.QLabel = QtWidgets.QLabel(self.attraction_QScrollArea_object)
elif container == "bookmarks_tab_QScrollArea_object":
self.QLabel = QtWidgets.QLabel(self.bookmarks_tab_QScrollArea_object)
elif container == "bookmarks_tab_top_groupBox_bar":
self.QLabel = QtWidgets.QLabel(self.bookmarks_tab_top_groupBox_bar)
elif container == "help_menu_groupBox":
self.QLabel = QtWidgets.QLabel(self.help_menu_groupBox)
elif container == "attractions_QGroupBox_bar":
self.QLabel = QtWidgets.QLabel(self.attractions_QGroupBox_bar)
elif container == "sources_tab_widget":
self.QLabel = QtWidgets.QLabel(self.sources_tab_widget)
elif container == "report_window_groupBox":
self.QLabel = QtWidgets.QLabel(self.report_window)
elif container == "documentation_window_QGroupBox":
self.QLabel = QtWidgets.QLabel(self.documentation_window)
elif container == "title_window_central_widget":
self.QLabel = QtWidgets.QLabel(self.title_window_central_widget)
# Geometry of QLabel is specified by the passed function parameters
self.QLabel.setGeometry(QtCore.QRect(x_coordinate, y_coordinate, width, length))
return self.QLabel
# Upon being called, this function creates a QComboBox associated with a container that is specified by the string
# parameter (container). The QLabel's geometry is specified by the location parameters (x_coordinate, y_coordinate)
# and the size parameters (width, length) passed through the function.
#
# Returns a QComboBox object
def create_QComboBox(self, container, x_coordinate, y_coordinate, width, length):
global location_and_filters_QGroupBox
global attraction_QScrollArea_object
global attractions_QGroupBox_bar
# Creates and associates QComboBox to specified container
if container == "location_and_filters_QGroupBox":
self.QComboBox = QtWidgets.QComboBox(self.location_and_filters_QGroupBox)
elif container == "attractions_QGroupBox_bar":
self.QComboBox = QtWidgets.QComboBox(self.attractions_QGroupBox_bar)
elif container == "title_window_central_widget":
self.QComboBox = QtWidgets.QComboBox(self.title_window_central_widget)
# Geometry of QComboBox is specified by the passed function parameters
self.QComboBox.setGeometry(QtCore.QRect(x_coordinate, y_coordinate, width, length))
return self.QComboBox
# Upon being called, this function creates a QCheckBox associated with a container that is specified by the string
# parameter (container). The QLabel's geometry is specified by the location parameters (x_coordinate, y_coordinate)
# and the size parameters (width, length) passed through the function.
#
# Returns a QComboBox object
def create_QCheckBox(self, container, x_coordinate, y_coordinate, width, length):
global location_and_filters_QGroupBox
global attraction_QScrollArea_object
# Creates and associates QComboBox to specified container
if container == "location_and_filters_QGroupBox":
self.QCheckBox = QtWidgets.QCheckBox(self.location_and_filters_QGroupBox)
# Geometry of QCheckBox is specified by the passed function parameters
self.QCheckBox.setGeometry(QtCore.QRect(x_coordinate, y_coordinate, width, length))
return self.QCheckBox
# This function creates an object container that holds all of the attraction's information and displays it within
# the application's scrollable area. The object consists of the attraction image, attraction details, and
# corresponding geographical maps that mark the attraction's location. Buttons are also included to expand the
# geographical map preview and to link the user to the attraction's official website.
#
# Returns a QGroupBox object
def create_QScrollArea_object(self, Ycoor, attraction):
global attraction_QScrollArea_object
# The QGroupBox container is created and added to the QScrollArea layout
self.attraction_QScrollArea_object = QtWidgets.QGroupBox(self.widget)
self.attraction_QScrollArea_object.setFixedSize(884, 220)
self.attraction_QScrollArea_object.setLayout(QtWidgets.QVBoxLayout())
# A QLabel is created to display an image of the attraction set using QPixmap
self.attraction_image = QtWidgets.QLabel(self.attraction_QScrollArea_object)
image_address = "./Attraction Pictures/" + str(attraction[0]) + " - " + str(attraction[4]) + ".jpg"
self.attraction_image.setPixmap(QtGui.QPixmap(image_address))
self.attraction_image.setScaledContents(True)
self.attraction_image.setFixedSize(220, 220)
self.attraction_image.show()
# A QToolButton is created to display the bookmark icon set using QPixmap and performs actions specified by the
# control_bookmarks function.
self.bookmark_icon = QtWidgets.QToolButton(self.attraction_QScrollArea_object)
self.bookmark_icon.setObjectName("bookmark")
self.bookmark_icon.setProperty("unactivated", True)
self.bookmark_icon.setGeometry(10, 10, 30, 30)
self.bookmark_icon.setIcon(QtGui.QIcon("Application Pictures/Bookmark Icons/unchecked bookmark.png"))
self.bookmark_icon.setIconSize(QtCore.QSize(512, 512))
self.bookmark_icon.setStyleSheet("QToolButton { background-color: transparent; border: 0px }");
# When the bookmark icon is clicked, the bookmark can be added or removed based on the icon's state of activation
self.bookmark_icon.clicked.connect(self.control_bookmarks)
labelXPos = 230
labelYPos = 95
converted_list = ''
for element in attraction:
if element == attraction[0]:
converted_list = converted_list + str(element)
else:
converted_list = converted_list + ',|' + str(element)
attraction_details_string = "[" + (converted_list) + "]"
# A hidden QLabel holds the attraction's information so the object's attributes can be read after creation
self.attraction_info_QLabel = self.create_QLabel("attraction_QScrollArea_object", 0, 0, 600, 50)
self.attraction_info_QLabel.setObjectName("attraction_info_QLabel")
self.attraction_info_QLabel.setText(attraction_details_string)
self.attraction_info_QLabel.setHidden(True)
# A QLabel is created to display the attraction title
self.attraction_title_QLabel = self.create_QLabel("attraction_QScrollArea_object", labelXPos, -5, 450, 50)
self.attraction_title_QLabel.setObjectName("attractionName")
self.attraction_title_QLabel.setText((str(attraction[1])))
# A QLabel is created to display the attraction's numeric rating [0-5]
self.rating_QLabel = self.create_QLabel("attraction_QScrollArea_object", labelXPos + 350, -5, 50, 50)
self.rating_QLabel.setObjectName("rating")
self.rating_QLabel.setText((str(attraction[8])))
# A QLabel is created and set to display an image of the attraction's rating through star icons. The rating
# displayed through the icons is the floored to the nearest 0.5 decimal.
# Ex. 4.8 would be represented as 4.5 and 2.9 would be represented as 2.5
# The rating decimal is intially set to 5.0
min_star_rating = 5.0
# The rating decimal is decreased in increments of 0.5 until the nearest 0.5 floored decimal
for i in range(10):
if (float(attraction[8]) < min_star_rating):
min_star_rating = min_star_rating - 0.5
else:
# Rating icon label is created and set to the specified rating image using QPixmap
self.rating_icon = QtWidgets.QLabel(self.attraction_QScrollArea_object)
self.rating_icon.setPixmap(QtGui.QPixmap("./Application Pictures/Star Ratings/" + str(min_star_rating)
+ " star.png"))
self.rating_icon.setScaledContents(True)
self.rating_icon.setFixedSize(85, 16)
self.rating_icon.move(600, 12)
self.rating_icon.show()
break
# A QLabel representing the distance from the specified location is conditionally created. If the latitudinal
# and longitudinal fields are not empty and are integers then the distance is calculated and shown by a QLabel.
# If the condition is not met, only the attraction's location (city, state) is displayed.
if self.latitude_input.text() != "" and self.longitude_input.text() != "" and \
self.is_float(str(self.latitude_input.text())) and self.is_float(str(self.longitude_input.text())):
# Distance from specified location and attraction is calculated
distance_from_user_location = distance.distance(
((self.latitude_input.text()), (self.longitude_input.text())), (attraction[13], attraction[14])).miles
# A QLabel is created to show the attraction's location and calculated distance
self.location_Qlabel = self.create_QLabel("attraction_QScrollArea_object", labelXPos, 17, 300, 50)
self.location_Qlabel.setObjectName("locationAndDistance")
self.location_Qlabel.setText((str(attraction[4]) + ", " + str(attraction[3])) + " - "
+ str('%.1f' % (distance_from_user_location)) + " miles away")
else:
# A QLabel is created to only show the attraction's location
self.location_Qlabel = self.create_QLabel("attraction_QScrollArea_object", labelXPos, 17, 200, 50)
self.location_Qlabel.setObjectName("locationAndDistance")
self.location_Qlabel.setText((str(attraction[4]) + ", " + str(attraction[3])))
# A QLabel is created to show the attraction's type. The type can be one of the four attraction types: Food,
# Nature/Outdoor, Entertainment, or Cultural/Historical.
self.type_QLabel = self.create_QLabel("attraction_QScrollArea_object", labelXPos, labelYPos + 20, 200, 50)
self.type_QLabel.setText((str(attraction[5])))
# A QLabel is created to display the attraction's relative cost
self.price_QLabel = self.create_QLabel("attraction_QScrollArea_object", labelXPos, labelYPos + 40, 200, 50)
if (str(attraction[6])) == '1':
self.price_QLabel.setText("Price Level - $")
elif (str(attraction[6])) == '2':
self.price_QLabel.setText("Price Level - $$")
else:
self.price_QLabel.setText("Price Level - $$$")
# A QLabel is created to display the attraction's relative busyness level
self.busyness_QLabel = self.create_QLabel("attraction_QScrollArea_object", labelXPos, labelYPos + 60, 200, 50)
if (str(attraction[7])) == '1':
self.busyness_QLabel.setText("Low Busyness")
elif (str(attraction[7])) == '2':
self.busyness_QLabel.setText("Moderately Busy")
else:
self.busyness_QLabel.setText("Very Busy")
# A QLabel is created to display whether an attraction is
# wheelchair accessible / family friendly / pet friendly
wheelchair_family_pet_values = ""
if ((attraction[9])):
wheelchair_family_pet_values = wheelchair_family_pet_values + "Wheelchair Accessible" + "\n"
if ((attraction[10])):
wheelchair_family_pet_values = wheelchair_family_pet_values + "Family Friendly" + "\n"
if ((attraction[11])):
wheelchair_family_pet_values = wheelchair_family_pet_values + "Pet Friendly"
self.wheelchair_family_pet_QLabel = self.create_QLabel("attraction_QScrollArea_object", labelXPos + 170,
labelYPos + 35, 200, 50)
self.wheelchair_family_pet_QLabel.setText(wheelchair_family_pet_values)
# A QLabel is created to display the coordinate location of the attraction (latitude, longitude)
self.coordinate_location_QLabel = self.create_QLabel("attraction_QScrollArea_object", labelXPos, labelYPos + 80,
200, 50)
self.coordinate_location_QLabel.setText(
"Location: (" + str('%.3f' % (attraction[13])) + "," + str('%.3f' % (attraction[14])) + ")")
# A hidden QLabel is created to be accessed later after the creation of the object
self.coordinate_info_QLabel = self.create_QLabel("attraction_QScrollArea_object", 0, 0, 200, 50)
self.coordinate_info_QLabel.setObjectName("Location")
self.coordinate_info_QLabel.setText(str('%.6f' % (attraction[14])) + "," + str('%.6f' % (attraction[13])))
self.coordinate_info_QLabel.hide()
# A QLabel is created to display the attraction's description
self.description_QLabel = self.create_QLabel("attraction_QScrollArea_object", labelXPos, 15, 454, 125)
self.description_QLabel.setWordWrap(True)
self.description_QLabel.setText((str(attraction[2])))
# A QGroupBox is created to hold the map data
self.map_container = QtWidgets.QGroupBox(self.attraction_QScrollArea_object)
self.map_container.setGeometry(QtCore.QRect(675, -10, 220, 220))
self.map_container.setEnabled(True)
self.map_container.setFlat(True)
# The created QGroupBox container"s layout is set to hold the web widget
self.map_frame = QtWidgets.QVBoxLayout(self.map_container)
# The attraction map is centered around the coordinates of the attraction
coordinate = (attraction[13], attraction[14])
map = folium.Map(zoom_start=15, location=coordinate)
folium.Marker(
location=coordinate,
icon=folium.Icon(color="red", icon='circle', prefix='fa'),
).add_to(map)
if (self.latitude_input.text() != "" and self.longitude_input.text() != "" and self.is_float(
str(self.latitude_input.text())) and self.is_float(str(self.longitude_input.text()))):
entered_location_coordinate = (float(self.latitude_input.text()), float(self.longitude_input.text()))
folium.Marker(
location=entered_location_coordinate,
icon=folium.Icon(color="darkgreen", icon='user'),
).add_to(map)
# Save map data to data object
data = io.BytesIO()
map.save(data, close_file=False)
webView = QWebEngineView()
# Sets the web widget to the map data
webView.setHtml(data.getvalue().decode())
# Adds the map data to the QGroupBox layout
self.map_frame.addWidget(webView)
# A QToolButton is made to create an expanded map window when clicked
self.expand_map_button = QtWidgets.QToolButton(self.attraction_QScrollArea_object)
self.expand_map_button.setGeometry(690, 198, 94, 17)
self.expand_map_button.setText("Expand Map ↗︎")
# When this QToolButton is pressed, an expanded window of the object's coordinates is created
self.expand_map_button.clicked.connect(self.show_expanded_map_window)
# A QToolButton is created to open the website of an attraction in a new window when clicked
self.website_button = QtWidgets.QToolButton(self.attraction_QScrollArea_object)
self.website_button.setGeometry(786, 198, 94, 17)
self.website_button.setText("Website ↗︎")
# When this QToolButton is pressed, a redirect to the attraction's website occurs
if (str(attraction[12]).startswith("http://")):
web_link = str(attraction[12]).replace("http://", "https://")
elif (str(attraction[12]).startswith("https://")):
web_link = str(attraction[12])
else:
web_link = "https://" + str(attraction[12])
self.website_button.clicked.connect(lambda: webbrowser.open(web_link))
# A QFrame.Hline is created to organize different parts of the attraction object
self.object_line = QtWidgets.QFrame(self.attraction_QScrollArea_object)
self.object_line.setGeometry(QtCore.QRect(235, 110, 440, 10))
self.object_line.setFrameShape(QtWidgets.QFrame.HLine)
self.object_line.setFrameShadow(QtWidgets.QFrame.Sunken)
# The QScrollArea's layout adds the attraction object to itself to display
self.verticalLayout_3.addWidget(self.attraction_QScrollArea_object)
return self.attraction_QScrollArea_object
# A function that contols the addition and deletion of QScrollArea attraction objects
def control_attractions_QScrollArea(self):
global filtered_attractions_list
# Removes any previously displayed result objects
if (len(self.attractions_QScrollArea_widget_container.children()) > 0):
attractions_QScrollArea_widget_list = self.attractions_QScrollArea_widget_container.children()
for i in reversed(range(len(self.attractions_QScrollArea_widget_container.children()))):
if i > 0:
attractions_QScrollArea_widget_list[i].deleteLater()
# Adds all filtered result objects to the attractions_QScrollArea
Ycoor = 0
for index in range(len(filtered_attractions_list)):
self.create_QScrollArea_object(Ycoor, filtered_attractions_list[index])
Ycoor = Ycoor + 200
self.attractions_QScrollArea.setWidget(self.attractions_QScrollArea_widget_container)
self.attractions_QScrollArea.verticalScrollBar().setSliderPosition(0)
# A function to rerun the suggesting algorithm, based on user changes. This function gets the entered preferences
# in the state, city, and type QComboBoxes as well as the wheelchair accessibility, family friendly, and pet friendly
# QCheckBoxes. Using the entered values, a request to the database is sent to create a list of attractions that
# satisfy the user's preferences. Using the filtered attractions, attraction objects are created to display the
# attractions.
def get_current_filter_field_values(self, _):
global filtered_attractions_list
global location_and_filters_QGroupBox
_translate = QtCore.QCoreApplication.translate
# Choosing which state to filter by, based on the state dropdown menu choice
if self.state_filter_QComboBox.currentText() == "No preference":
current_selected_state = "None"
else:
current_selected_state = self.state_filter_QComboBox.currentText()
# Choosing which city to filter by, based on the city dropdown menu choice
if self.city_filter_QComboBox.currentText() == "No preference":
current_selected_city = "None"
else:
current_selected_city = self.city_filter_QComboBox.currentText()
# Choosing which container to filter by, based on the container dropdown menu choice
if self.type_filter_QComboBox.currentText() == "No preference":
current_selected_type = "None"
else:
current_selected_type = self.type_filter_QComboBox.currentText()
# Choosing whether or not to filter by wheelchair accessibility, based on if its respective checkbox is checked
current_checked_wheelchair_accessibility = self.wheelchair_access_filter_QCheckBox.isChecked()
# Choosing whether or not to filter by family friendly, based on if its respective checkbox is checked
current_checked_family_friendliness = self.family_friendly_filter_QCheckBox.isChecked()
# Choosing whether or not to filter by pet friendly, based on if its respective checkbox is checked
current_checked_pet_friendliness = self.pet_friendly_filter_QCheckBox.isChecked()
# Choosing what attribute to sort by, based on the selection of the sorting dropdown menu
current_sorter = self.sorting_QComboBox.currentText()
# Creating a list of attributes to filter and sort by based on the entered attributes
attribute_list = [str(current_selected_state), str(current_selected_city), str(current_selected_type),
str(current_checked_wheelchair_accessibility), str(current_checked_family_friendliness),
str(current_checked_pet_friendliness)]
# Since database filters take a None keyword or a string name value, all "None" or "False" entered values are
# converted to the accepted None keyword
for index in range(len(attribute_list)):
if (attribute_list[index] == "None" or attribute_list[index] == "False"):
attribute_list[index] = None
# All attractions are stored in a separate storage in order to retrieve all sources and references of all
# attractions to later display in the sources tab of the application
all_attractions = application_database.getAttractions(filters=application_filter_request.FilterRequest(None, None,
None, None,
None, None))
# Filtering attractions based on the entered filter attributes. A request with the entered attributes is sent to
# retrieve values from the PostgresSQL database. A dynamic database containing all satisfactory attractions is
# formed. Changes in filters updates the filtered database based on the new set of filters
filtered_attractions = application_database.getAttractions(
filters=application_filter_request.FilterRequest(attribute_list[0], attribute_list[1], attribute_list[2],
attribute_list[3], attribute_list[4], attribute_list[5]))
filtered_attractions_list = filtered_attractions
attraction_adjustment = 0
if (len(filtered_attractions_list) > 30):
attraction_adjustment = 2
# Selective display of singular or plural "Attraction" + "Found"
if (len(filtered_attractions_list)) == 1:
self.num_of_attractions_QLabel.setText((str(len(filtered_attractions_list)+attraction_adjustment)) + " Attraction Found")
else:
self.num_of_attractions_QLabel.setText(
_translate("MainWindow", (str(len(filtered_attractions_list)+attraction_adjustment)) + " Attractions Found"))
# Sort the filtered attractions
self.sort_attractions()
# Display the filtered and sorted attractions
self.control_attractions_QScrollArea()
# The distance from entered location and number of objects displayed are calculated. If the QComboBox specifying
# desired distance is enabled (when both latitude and longitude are correctly entered) then distance is
# calculated. Simultaneously, a QLabel is updated to reflect the number of objects being shown in the QScrollArea.
if (self.radius_QComboBox.isEnabled()):
global radius_checked
# Holds the boolean value to whether the radius_QComoBox has been checked
radius_checked = True
# If a specific desired distance is specified, attractions not in a radius of that distance will be removed.
# This desired distance value will be compared with the distance calculated for every attraction in order to
# determine if that attraction lies within the inputted radius.
if (self.radius_QComboBox.currentText() != "Any distance"):
# The total count of all attraction objects being displayed within attraction_QScrollArea
count_of_objects_shown = len(self.attractions_QScrollArea_widget_container.children()) - 1
for index in range(len(self.attractions_QScrollArea_widget_container.children())):
if self.attractions_QScrollArea_widget_container.children()[
index].isWidgetType() == QtWidgets.QGroupBox:
object_distance_QLabel = self.attractions_QScrollArea_widget_container.children()[
index].findChild(QtWidgets.QLabel, 'locationAndDistance').text()
index_of_letter_m = object_distance_QLabel.index("miles")
index_of_hyphen = object_distance_QLabel.index("-")
if (float(object_distance_QLabel[(index_of_hyphen + 1):(index_of_letter_m - 1)]) < float(
self.radius_QComboBox.currentText()[10:12])):
self.attractions_QScrollArea_widget_container.children()[index].show()
else:
self.attractions_QScrollArea_widget_container.children()[index].hide()
count_of_objects_shown = count_of_objects_shown - 1
attraction_adjustment = 0
if (len(filtered_attractions_list) > 30):
attraction_adjustment = 2
# The QLabel displaying the total number of results is updated as the number of shown attractions changes
if (count_of_objects_shown) == 1:
self.num_of_attractions_QLabel.setText((str(count_of_objects_shown)+attraction_adjustment) + " Attraction Found")
else:
self.num_of_attractions_QLabel.setText((str(count_of_objects_shown)+attraction_adjustment) + " Attractions Found")
attribute_list = [None, None, None, None, None, None]
# Create an output report text file, based on the attributes the user selected
with open('outputreport.txt', 'a') as f:
stringAccessedTime = strftime("%Y-%m-%d %H:%M:%S", gmtime())
locationOfSpace = stringAccessedTime.index(" ")
f.write("⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯")
f.write("Activity Logged Date: " + stringAccessedTime[
:locationOfSpace] + " Time Of Action: " + stringAccessedTime[
(locationOfSpace + 1):])
f.write("\n")
f.write("Selected State: ")
f.write(current_selected_state)
f.write("\n")
f.write("Selected City: ")
f.write(current_selected_city)
f.write("\n")
f.write("Selected Type: ")
f.write(current_selected_type)
f.write("\n")
f.write("Wheelchair Accessibility is Checked: ")
f.write(str(current_checked_wheelchair_accessibility))
f.write("\n")
f.write("Family Friendliness is Checked: ")
f.write(str(current_checked_family_friendliness))
f.write("\n")
f.write("Pet Friendliness is Checked: ")
f.write(str(current_checked_pet_friendliness))
f.write("\n")
f.write("Currently sorting by: ")
f.write(current_sorter)
f.write("\n")
for element in filtered_attractions_list:
f.write("Filtered Attraction: " + "(id: " + str(element[0]) + ")" + ", " +
str(element[1]) + ", " + str(element[5]) + ", " + str(element[4]) + ", " + str(element[2]))
f.write("\n")
f.close()
# The function to sort the displayed attractions, by some attribute (price, distance, busyness, rating)
def sort_attractions(self):
# A function to find the distance between an attraction and a given set of coordinates
def calculate_distance_to_entered_location(data):
return distance.distance(((self.latitude_input.text()), (self.longitude_input.text())),
(data[13], data[14])).miles
# Sort by nearest attractions
if self.sorting_QComboBox.currentText() == "Nearest attractions":
filtered_attractions_list.sort(key=calculate_distance_to_entered_location)
# Sorting by highest rating
if self.sorting_QComboBox.currentText() == "Highest rated":
filtered_attractions_list.sort(key=itemgetter(8), reverse=True)
# Sorting by lowest price
if self.sorting_QComboBox.currentText() == "Lowest price":
filtered_attractions_list.sort(key=itemgetter(6), reverse=False)
# Sorting by lowest traffic
if self.sorting_QComboBox.currentText() == "Lowest traffic":
filtered_attractions_list.sort(key=itemgetter(7), reverse=False)
# Changes to bookmark icon when it is clicked
def control_bookmarks(self, _):
self.bookmark_icon = self.attraction_QScrollArea_object.sender().parent().findChild(QtWidgets.QToolButton,
'bookmark')
# If the bookmark is not selected, change it to activated, change its icon, add its bookmark to the bookmarks tab
if (self.bookmark_icon.property("unactivated") == True):
self.bookmark_icon.setProperty("unactivated", False)
self.bookmark_icon.setIcon(QtGui.QIcon("Application Pictures/Bookmark Icons/checked bookmark.png"))
self.add_bookmark(_)
if len(self.bookmarks_scrollArea_object_container.children()) == 2:
self.num_of_bookmarks_QLabel.setText(
(str(len(self.bookmarks_scrollArea_object_container.children()) - 1) + " Total Bookmark Saved"))
else:
self.num_of_bookmarks_QLabel.setText(
(str(len(self.bookmarks_scrollArea_object_container.children()) - 1) + " Total Bookmarks Saved"))
self.bookmark_icon.setIconSize(QtCore.QSize(1024, 1024))
self.bookmarks_QScrollArea.setWidget(self.bookmarks_scrollArea_object_container)
# If the bookmark is selected, change it to unactivated, change its icon, add remove bookmark from the bookmarks tab
else:
self.bookmark_icon.setProperty("unactivated", True)
self.bookmark_icon.setIcon(QtGui.QIcon("Application Pictures/Bookmark Icons/unchecked bookmark.png"))
self.remove_bookmark(_)
if len(self.bookmarks_scrollArea_object_container.children()) == 3:
self.num_of_bookmarks_QLabel.setText(
(str(len(self.bookmarks_scrollArea_object_container.children()) - 2) + " Total Bookmark Saved"))
else:
self.num_of_bookmarks_QLabel.setText(
(str(len(self.bookmarks_scrollArea_object_container.children()) - 2) + " Total Bookmarks Saved"))
self.bookmark_icon.setIconSize(QtCore.QSize(1024, 1024))
self.bookmark_icon.setStyleSheet("QToolButton { background-color: transparent; border: 0px }");
self.bookmarks_QScrollArea.verticalScrollBar().setSliderPosition(0)
# A function ran to clear all bookmarks
def clear_all_bookmarks(self, _):
for object in self.bookmarks_scrollArea_object_container.children():
try:
attraction = object.findChild(QtWidgets.QLabel, 'attractionName').text()
for object_2 in self.attractions_QScrollArea_widget_container.children():
try:
if (object_2.findChild(QtWidgets.QLabel, 'attractionName').text() == object.findChild(
QtWidgets.QLabel, 'attractionName').text()):
object_2.findChild(QtWidgets.QToolButton, 'bookmark').setIcon(
QtGui.QIcon("Application Pictures/Bookmark Icons/unchecked bookmark.png"))
except:
continue
object.deleteLater()
except:
continue
self.num_of_bookmarks_QLabel.setText("0 Total Bookmarks Saved")
# A function for the code to remove a function
def remove_bookmark(self, _):
name = self.attraction_QScrollArea_object.sender().parent().findChild(QtWidgets.QLabel, 'attractionName').text()
for object in self.bookmarks_scrollArea_object_container.children():
try:
if (object.findChild(QtWidgets.QLabel, 'attractionName').text() == name):
for object_2 in self.attractions_QScrollArea_widget_container.children():
try:
object_2.findChild(QtWidgets.QToolButton, 'bookmark').setIcon(
QtGui.QIcon("Application Pictures/Bookmark Icons/unchecked bookmark.png"))
except:
continue
object.deleteLater()
except:
continue
# The function to add a new attraction to the bookmarks tab, with all of its attribute information
def add_bookmark(self, _):
attraction = (self.attraction_QScrollArea_object.sender().parent().findChild(QtWidgets.QLabel,
'attraction_info_QLabel').text()).strip(
'][').split(',|')
_translate = QtCore.QCoreApplication.translate
# Creating an area for multiple bookmarks to be displayed, with a scrollbar
self.bookmarks_tab_QScrollArea_object = QtWidgets.QGroupBox(self.bookmarks_scrollArea_object_container)
self.bookmarks_tab_QScrollArea_object.setFixedSize(884, 220)
self.bookmarks_tab_QScrollArea_object.setLayout(QtWidgets.QVBoxLayout())
labelXPos = 230
labelYPos = 25
# Display the bookmarked attraction's title
self.bookmarks_tab_attraction_title = self.create_QLabel("bookmarks_tab_QScrollArea_object", labelXPos, -5, 450,
50)
self.bookmarks_tab_attraction_title.setObjectName("attractionName")
self.bookmarks_tab_attraction_title.setText((str(attraction[1])))
# Display the bookmarked attraction's rating
self.bookmarks_tab_rating_label = self.create_QLabel("bookmarks_tab_QScrollArea_object", labelXPos + 350, -5,
50, 50)
self.bookmarks_tab_rating_label.setObjectName("rating")
self.bookmarks_tab_rating_label.setText((str(attraction[8])))
bookmark_object_min_star_rating = 5.0
# Display different star icon based on its rating
for i in range(10):
if (float(attraction[8]) < bookmark_object_min_star_rating):
bookmark_object_min_star_rating = bookmark_object_min_star_rating - 0.5
else:
self.rating_icon = QtWidgets.QLabel(self.bookmarks_tab_QScrollArea_object)
self.rating_icon.setPixmap(
QtGui.QPixmap(
"./Application Pictures/Star Ratings/" + str(bookmark_object_min_star_rating) + " star.png"))
self.rating_icon.setScaledContents(True)
self.rating_icon.setFixedSize(85, 16)
self.rating_icon.move(600, 12)
self.rating_icon.show()
break
# Display the bookmarked attraction's location
if (self.latitude_input.text() != "" and self.longitude_input.text() != "" and self.is_float(
str(self.latitude_input.text())) and self.is_float(str(self.longitude_input.text()))):
self.location_Qlabel = self.create_QLabel("bookmarks_tab_QScrollArea_object", labelXPos, labelYPos - 8, 350,
50)
self.location_Qlabel.setObjectName("locationAndDistance")
distanceFromUserLocation = distance.distance(((self.latitude_input.text()), (self.longitude_input.text())),
(attraction[13], attraction[14])).miles
self.location_Qlabel.setText((str(attraction[4]) + ", " + str(attraction[3])) + " - " + str(
'%.1f' % (distanceFromUserLocation)) + " miles away")
else:
self.bookmarks_tab_location_label = self.create_QLabel("bookmarks_tab_QScrollArea_object", labelXPos,
labelYPos - 3, 200, 50)
self.bookmarks_tab_location_label.setObjectName("locationAndDistance")
self.bookmarks_tab_location_label.setText((str(attraction[4]) + ", " + str(attraction[3])))
self.bookmarks_tab_type_label = self.create_QLabel("bookmarks_tab_QScrollArea_object", labelXPos,
labelYPos + 20, 200, 50)
self.bookmarks_tab_type_label.setText((str(attraction[5])))
self.bookmarks_tab_price_label = self.create_QLabel("bookmarks_tab_QScrollArea_object", labelXPos,
labelYPos + 40, 200, 50)
# Display the bookmarked attraction's price
if (str(attraction[6])) == '1':
self.bookmarks_tab_price_label.setText("Price Level - $")
elif (str(attraction[6])) == '2':
self.bookmarks_tab_price_label.setText("Price Level - $$")
else:
self.bookmarks_tab_price_label.setText("Price Level - $$$")
# Display the bookmarked attraction's busyness
self.bookmarks_tab_busyness_label = self.create_QLabel("bookmarks_tab_QScrollArea_object", labelXPos,
labelYPos + 60, 200, 50)
if (str(attraction[7])) == '1':
self.bookmarks_tab_busyness_label.setText("Low Busyness")
elif (str(attraction[7])) == '2':
self.bookmarks_tab_busyness_label.setText("Moderately Busy")
else:
self.bookmarks_tab_busyness_label.setText("Very Busy")
# A QLabel is created on the bookmarks tab to display whether an attraction is
# wheelchair accessible / family friendly / pet friendly
bookmark_wheelchair_family_pet_values = ""
if ((attraction[9])):
bookmark_wheelchair_family_pet_values = bookmark_wheelchair_family_pet_values + "Wheelchair Accessible" + "\n"
if ((attraction[10])):
bookmark_wheelchair_family_pet_values = bookmark_wheelchair_family_pet_values + "Family Friendly" + "\n"
if ((attraction[11])):
bookmark_wheelchair_family_pet_values = bookmark_wheelchair_family_pet_values + "Pet Friendly"
self.bookmark_wheelchair_family_pet_QLabel = self.create_QLabel("bookmarks_tab_QScrollArea_object", labelXPos + 170,
labelYPos + 20, 200, 50)
self.bookmark_wheelchair_family_pet_QLabel.setText(bookmark_wheelchair_family_pet_values)
# Display the bookmarked attraction's coordinates
self.bookmarks_tab_coordinate_location_label = self.create_QLabel("bookmarks_tab_QScrollArea_object", labelXPos,
labelYPos + 80, 200, 50)
self.bookmarks_tab_coordinate_location_label.setText(
"Location: (" + str('%.3f' % (float(attraction[13]))) + "," + str('%.3f' % float((attraction[14]))) + ")")
self.bookmarks_tab_coordinate_location_label = self.create_QLabel("bookmarks_tab_QScrollArea_object", 0, 0, 200,
50)
self.bookmarks_tab_coordinate_location_label.setText(
str('%.6f' % float(attraction[14])) + "," + str('%.6f' % float(attraction[13])))
self.bookmarks_tab_coordinate_location_label.setObjectName("Location")
self.bookmarks_tab_coordinate_location_label.hide()
# Display the bookmarked attraction's brief description
self.bookmarks_tab_description_label = self.create_QLabel("bookmarks_tab_QScrollArea_object", labelXPos,
labelYPos + 93, 454, 125)
self.bookmarks_tab_description_label.setWordWrap(True)
self.bookmarks_tab_description_label.setText((" " + str(attraction[2])))
# Display the bookmarked attraction's image
imageAddress = "./Attraction Pictures/" + str(attraction[0]) + " - " + str(attraction[4]) + ".jpg"
self.bookmark_object_attraction_image = QtWidgets.QLabel(self.bookmarks_tab_QScrollArea_object)
self.bookmark_object_attraction_image.setPixmap(QtGui.QPixmap(imageAddress))
self.bookmark_object_attraction_image.setScaledContents(True)
self.bookmark_object_attraction_image.setFixedSize(220, 220)
self.bookmark_object_attraction_image.show()
# Display the bookmarked attraction's bookmarked status
self.bookmark_object_bookmark_icon = QtWidgets.QToolButton(self.bookmarks_tab_QScrollArea_object)
self.bookmark_object_bookmark_icon.setObjectName("bookmark")
self.bookmark_object_bookmark_icon.setProperty("unactivated", False)
self.bookmark_object_bookmark_icon.setGeometry(10, 10, 30, 30)
self.bookmark_object_bookmark_icon.setIcon(
QtGui.QIcon("Application Pictures/Bookmark Icons/checked bookmark.png"))
self.bookmark_object_bookmark_icon.setIconSize(QtCore.QSize(512, 512))
self.bookmark_object_bookmark_icon.setStyleSheet("QToolButton { background-color: transparent; border: 0px }");
self.bookmark_object_bookmark_icon.clicked.connect(self.control_bookmarks)
# Display the bookmarked attraction's map window
self.bookmark_object_map_container = QtWidgets.QGroupBox(self.bookmarks_tab_QScrollArea_object)
self.bookmark_object_map_container.setGeometry(QtCore.QRect(675, -10, 220, 220))
self.bookmark_object_map_container.setEnabled(True)
self.bookmark_object_map_container.setFlat(True)
self.bookmark_object_map_frame = QtWidgets.QVBoxLayout(self.bookmark_object_map_container)
# The bookmarked attraction's map is centered around its coordinate
coordinate = (float(attraction[13]), float(attraction[14]))
map = folium.Map(
zoom_start=15,
location=coordinate
)
folium.Marker(
location=coordinate,
icon = folium.Icon(color="darkgreen", icon='user')
).add_to(map)
# save map data to data object
data = io.BytesIO()
map.save(data, close_file=False)
webView = QWebEngineView()
webView.setHtml(data.getvalue().decode())
self.bookmark_object_map_frame.addWidget(webView)
# Creating a button to expand the button
self.bookmark_object_expand_map_button = QtWidgets.QToolButton(self.bookmarks_tab_QScrollArea_object)
self.bookmark_object_expand_map_button.setGeometry(690, 198, 94, 17)
self.bookmark_object_expand_map_button.setText("Expand Map ↗︎")
self.bookmark_object_expand_map_button.clicked.connect(self.show_expanded_map_window)
# Create a button to open the attraction's website
self.bookmark_object_website_redirect = QtWidgets.QToolButton(self.bookmarks_tab_QScrollArea_object)
self.bookmark_object_website_redirect.setGeometry(786, 198, 94, 17)
self.bookmark_object_website_redirect.setText(_translate("MainWindow", "Website ↗︎"))
if (str(attraction[12]).startswith("http://")):
web_link = str(attraction[12]).replace("http://","https://")
elif (str(attraction[12]).startswith("https://")):
web_link = str(attraction[12])
else:
web_link = "https://"+str(attraction[12])
self.bookmark_object_website_redirect.clicked.connect(lambda: webbrowser.open(web_link))
# Create a line on the bookmark tab
self.bookmark_object_line = QtWidgets.QFrame(self.bookmarks_tab_QScrollArea_object)
self.bookmark_object_line.setGeometry(QtCore.QRect(235, 138, 440, 10))
self.bookmark_object_line.setFrameShape(QtWidgets.QFrame.HLine)
self.bookmark_object_line.setFrameShadow(QtWidgets.QFrame.Sunken)
self.bookmarks_container_vertical_layout.addWidget(self.bookmarks_tab_QScrollArea_object)
# Detect a change in radius
def detect_change_in_desired_distance(self, _):
global radius_checked
if (radius_checked):
count_of_objects_shown = len(self.attractions_QScrollArea_widget_container.children()) - 1
if (self.radius_QComboBox.isEnabled()):
for index in range(len(self.attractions_QScrollArea_widget_container.children())):
if index != 0:
object_distance_QLabel = self.attractions_QScrollArea_widget_container.children()[
index].findChild(QtWidgets.QLabel, 'locationAndDistance').text()
index_of_letter_m = object_distance_QLabel.index("m")
index_of_hyphen = object_distance_QLabel.index("-")
if (self.radius_QComboBox.currentText() != "Any distance"):
if (float(object_distance_QLabel[(index_of_hyphen + 1):(index_of_letter_m - 1)]) < float(
self.radius_QComboBox.currentText()[10:12])):
self.attractions_QScrollArea_widget_container.children()[index].show()
else:
self.attractions_QScrollArea_widget_container.children()[index].hide()
count_of_objects_shown = count_of_objects_shown - 1
else:
self.attractions_QScrollArea_widget_container.children()[index].show()
attraction_adjustment = 0
if (len(filtered_attractions_list) > 30):
attraction_adjustment = 2
if (count_of_objects_shown) == 1:
self.num_of_attractions_QLabel.setText((str(count_of_objects_shown+attraction_adjustment)) + " Attraction Found")
else:
self.num_of_attractions_QLabel.setText((str(count_of_objects_shown+attraction_adjustment)) + " Attractions Found")
# A function to check if latitude and longitude are filled, then allowing the user to access functions related to their location
def check_if_location_fields_are_filled(self, _):
if (self.latitude_input.text() != "" and self.longitude_input.text() != "" and self.is_float(
str(self.latitude_input.text())) and self.is_float(str(self.longitude_input.text()))):
self.radius_QComboBox.setEnabled(True)
self.show_entered_location_map_button.setEnabled((True))
try:
if (float(self.latitude_input.text()) != float(ipInfo.__getattr__("location")["latitude"]) or
float(self.longitude_input.text()) != float(ipInfo.__getattr__("location")["longitude"])):
location = geolocator.reverse((self.latitude_input.text()) + "," + (self.longitude_input.text()))
address = location.raw['address']
city = address.get('city', '')
state = address.get('state', '')
if (city != "" and city != " "):
self.current_location_QLabel.setText(str(city) + ", " + str(state))
elif (city == "" and state == ""):
self.current_location_QLabel.setText("Please enter a valid location")
else:
self.current_location_QLabel.setText(str(state))
else:
self.current_location_QLabel.setText("Please enter a valid location")
except:
self.current_location_QLabel.setText("Please enter a valid location")
else:
self.radius_QComboBox.setEnabled(False)
self.show_entered_location_map_button.setEnabled((False))
# The function ran to obtain user's latitude and longitude, when prompted
def find_current_location(self, _):
self.latitude_input.setText(str(ipInfo.__getattr__("location")["latitude"]))
self.longitude_input.setText(str(ipInfo.__getattr__("location")["longitude"]))
self.check_if_location_fields_are_filled
self.current_location_QLabel.setText(str(ipInfo.__getattr__("location")["city"]) + ", " + str(
ipInfo.__getattr__("location")["region"]["name"]))
# A function with logic to determine if the help menu should be shown, toggled on/off by the user
def control_help_menu_display(self, _):
global help_menu_QGroupBox
global click_count
if (click_count != 1):
click_count = click_count + 1
self.help_menu_groupBox.show()
else:
self.help_menu_groupBox.hide()
click_count = 0
# Showing documentation when clicked
def read_documentation(self, _):
# Creating the window that shows documentation
self.documentation_window = QtWidgets.QLabel()
self.documentation_window.setObjectName("documentation_window")
self.documentation_window.setFixedSize(800, 600)
self.documentation_window.setWindowTitle("Read Documentation")
self.documentation_window_central_widget = QtWidgets.QWidget(self.documentation_window)
self.documentation_window_central_widget.setFixedSize(800, 600)
self.documentation_window_QGroupBox = QtWidgets.QGroupBox(self.documentation_window_central_widget)
self.documentation_window_QGroupBox.setFixedSize(784, 554)
self.documentation_window_QGroupBox.move(8, 35)
self.documentation_window_QGroupBox.setEnabled(True)
self.documentation_window_QGroupBox.setFlat(True)
self.documentation_window_QGroupBox.setObjectName("documentationTextContainer")
self.documentation_QLabel = self.create_QLabel("documentation_window_QGroupBox", 343, 0, 200, 50)
self.documentation_QLabel.setText("Documentation")
self.documentation_QLabel.setObjectName("documentationTitle")
filename = os.path.abspath('Application Data and Documentation Files/FBLA Manual + Documentation.pdf')
view = QtWebEngineWidgets.QWebEngineView(self.documentation_window_QGroupBox)
settings = view.settings()
settings.setAttribute(QtWebEngineWidgets.QWebEngineSettings.PluginsEnabled, True)
url = QtCore.QUrl.fromLocalFile(filename)
view.load(url)
view.resize(780, 550)
view.move(2,2)
view.show()
self.documentation_window.show()
def show_QandA_window(self, _):
all_questions = [["Does the attraction finder cover all states?", "Yes, this application suggests attractions from all 50 states, covering each state’s largest cities."],
["Can I download my suggested attractions for further use?", "Yes, when running our application, we generate an output report for your further use."],
["How can I suggest an edit to an attraction?", "On the main window, the help menu offers you the ability to create a report. This gives you the option to tell us of an error by generating a user report."],
["I need some more information on the program.", "Sure, we have created a file for documentation of our program. Visit the help menu for program documentation."],
["How do I use the ‘my location’ feature?", "Our application is able to take your location and use it when looking for nearest attractions. By changing the sorting dropdown in the top right, you can sort attractions based on their distance to you. Each displayed attraction will also tell you its physical distance from you."],
["Why do some features not work?", "Most likely, you may have some wifi problems that prevent full use of internet features, such as finding your location and redirecting you to each attraction’s homepage. \nYou can also generate a user report in the event you encounter an error. \nWe also have created a documentation file that covers required libraries, system requirements, and more."],
["How do I find attractions close to where I am?", "You can do this by navigating to the location details window and selecting an option in the dropout menu under the area labelled \"Desired Distance From You.\""],
["How do I filter for whether attractions are pet friendly?", "You can do this by navigating to the \"Filter By:\" area and checking the box on the pet friendly option."],
["How do I find out how expensive it is to visit an attraction?", "This may be done by navigating to the center area where all the attractions are displayed and looking at the price rating. The price of an attraction is displayed as $, $$ or $$$."],
["Where are the sources used in this application provided?", "All sources can by found by navigating to the Sources, Licenses, and References tab positioned to the right of the Bookmarked Attractions tab."],
["How can I bookmark attractions?", "To bookmark a specific attraction, click on the bookmark icon placed at the top left of the attraction image."],
["Where can I see all of my bookmarked attractions?", "In order to view all of your bookmarked attractions, simply navigate to the Bookmarked Attractions tab to the right of the Find Attractions tab."],
["How can I create a user report?", "Navigate to the help menu on the Find Attractions tab. Opening the menu will show a button titled \"Create a report\". Uponing clicking this button, a new window will appear with fields for you to fill. Here you can customize the report to provide feedback and report any irregularities within the application." ],
["Is the shown data secured?", "Yes, the data is stored in a secure database named Postgres SQL. For more information about data security and protection, please read the documentation."],
["Is the database backed up and dynamic?", "Yes, the database is continuosly backed up on both the local computer as well as the server. The database is dynamic by contiuously storing the filtered attractions which are based on the user's specified attributes. The database is adaptive to the user's needs and dynamically appends user specified results and customized reports. "],