forked from osdag-admin/Osdag
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathosdagMainPage.py
854 lines (733 loc) · 39.8 KB
/
osdagMainPage.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
'''
INSTRUCTIONS TO USE OSDAG MAIN PAGE TEMPLATE(OsdagMainWindow):
----------------------------------------------------------------------------------------------------
Note: This code is designed to handle a 3 level structure, e.g. ,
..................................................................................................................
. Modules (Main Dictionary) .
. _______________________|______________________________________________________.......... . ((LEVEL 1))
. | | | | | | .
. Module_1 Module_2 Module_3 Module_4 Module_5 Module_6 (Keys of Main Dictionary)
........|..............|............|...........|....................|...............|............................
| | | | | |
| | | | | |
| | | [List/Tuple of Module Variants]| |
| | | | |
| | [List/Tuple of Module Variants] | |
| (UNDER DEVELOPMENT) (UNDER DEVELOPMENT) |
........|............................................................................|............................
. ____|________________________________..... ________________________|______...... (Sub Dictionaries)
. | | | | | | . ((LEVEL 2))
. Submodule_1 Submodule_2 Submodule_3 Submodule_1 Submodule_2 Submodule_3 (Keys of Sub Dictionaries)
. | | | | | | .
........|...............|...............|................|..................|..............|......................
| | | | | |
| | | | | |
| | | | | |
| | (UNDER DEVELOPMENT) | | |
| | [List/Tuple of Module Variants] | |
| [List/Tuple of Module Variants] | [List/Tuple of Module Variants]
| |
........|...................................................................|.....................................
. ____|________________________________..... _______________|_______________...... (Sub-Sub Dictionaries)
. | | | | | | . ((LEVEL 3))
. Sub-Submodule_1 Sub-Submodule_2 Sub-Submodule_3 Sub-Submodule_1 Sub-Submodule_2 Sub-Submodule_3 (Keys of Sub-Sub Dictionaries)
. | | | | | | .
........|...............|...............|....................|..................|..............|..................
| | | | | |
| (UNDER DEVELOPMENT) | [List/Tuple of Module Variants] | [List/Tuple of Module Variants]
| [List/Tuple of Module Variants] [List/Tuple of Module Variants]
[List/Tuple of Module Variants]
The Rules/Steps to use the template are(OsdagMainWindow):
-----------------------------------------------------------------------------
1) The data for the template structuring will go into a variable called self.Modules .
2) self.Modules must be a dictionary with keys as the name of modules in string format (LEVEL 1: Left Panel Buttons).
3) The values to these keys can be a dictionary(Modules), a List/Tuple(Module Variants) or self.Under_Development :
(i) If the value is a dictionary then it should contain keys as modules in string format and for values
read RULE 4 . (LEVEL 2: Tab for each module)
(ii) If the value is a List/Tuple then it should contain sub-lists/sub-tuples informing about the module variants :
(a) The module variants as sub-list/sub-tuple will have 3 values, Module_Name, Image_Path and Object_Name .
(b) The List/Tuple can have several sub-lists/sub-tuples but the last element should be a method,
which connects to the start button on the module variants' page and help launch a certain module.
(iii) If the value is self.Under_Development then that module/module variant is marked as UNDER DEVELOPMENT.
4) In case of RULE 3(i) if value of any sub-module key is a dictionary then that dictionary will follow the RULE 3
all over again and the values of the keys can be a dictionary(Sub-Modules), a List/Tuple(Sub-Module Variants) or
self.Under_Development:
(i) If the value is a dictionary then it should contain keys as sub-modules in string format and for values
read RULE 5 . (LEVEL 3 Sub Tab for each tab)
(ii) If the value is a List/Tuple then it should contain sub-lists/sub-tuples informing about the module variants :
(a) The module variants as sub-list/sub-tuple will have 3 values, Module_Name, Image_Path and Object_Name .
(b) The List/Tuple can have several sub-lists/sub-tuples but the last element should be a method,
which connects to the start button on the module variants' page and help launch a certain module.
(iii) If the value is self.Under_Development then that module/module variant is marked as UNDER DEVELOPMENT.
5) In case of RULE 4(i) if the value of any sub-module key is a dictionary then that dictionary will have keys as sub-sub-module
and the values can either be a List/Tuple(Sub-Sub-Module Variants) or self.Under_Development but not another dictionary:
(i) If the value is a List/Tuple then it should contain sub-lists/sub-tuples informing about the module variants :
(a) The module variants as sub-list/sub-tuple will have 3 values, Module_Name, Image_Path and Object_Name .
(b) The List/Tuple can have several sub-lists/sub-tuples but the last element should be a method,
which connects to the start button on the module variants' page and help launch a certain module.
(ii) If the value is self.Under_Development then that module/module variant is marked as UNDER DEVELOPMENT.
6) Object_Name, the third value in the sub-lists/sub-tuples, is used to tie to the Radiobuttons on each page thus making it easier to locate them. This is further used
in the methods to search the Radiobutton using it for the respective modules to be launched .
7) Any further Levels will result in an error .
'''
import os
from pathlib import Path
import re
from PyQt5.QtWidgets import QMessageBox,QApplication, QDialog, QMainWindow
import urllib.request
from update_version_check import Update
#from Thread import timer
from get_DPI_scale import scale
############################ Pre-Build Database Updation/Creation #################
sqlpath = Path('ResourceFiles/Database/Intg_osdag.sql')
sqlitepath = Path('ResourceFiles/Database/Intg_osdag.sqlite')
if sqlpath.exists():
if not sqlitepath.exists():
cmd = 'sqlite3 ' + str(sqlitepath) + ' < ' + str(sqlpath)
os.system(cmd)
sqlpath.touch()
print('Database Created')
elif sqlitepath.stat().st_size == 0 or sqlitepath.stat().st_mtime < sqlpath.stat().st_mtime - 1:
try:
sqlitenewpath = Path('ResourceFiles/Database/Intg_osdag_new.sqlite')
cmd = 'sqlite3 ' + str(sqlitenewpath) + ' < ' + str(sqlpath)
error = os.system(cmd)
print(error)
# if error != 0:
# raise Exception('SQL to SQLite conversion error 1')
# if sqlitenewpath.stat().st_size == 0:
# raise Exception('SQL to SQLite conversion error 2')
os.remove(sqlitepath)
sqlitenewpath.rename(sqlitepath)
sqlpath.touch()
print('Database Updated', sqlpath.stat().st_mtime, sqlitepath.stat().st_mtime)
except Exception as e:
sqlitenewpath.unlink()
print('Error: ', e)
#########################################################################################
from PyQt5.QtCore import pyqtSlot,pyqtSignal, QObject, Qt,QSize, QFile, QTextStream, QCoreApplication
from PyQt5.QtWidgets import QMainWindow, QDialog,QMessageBox, QFileDialog, QApplication, QWidget, QLabel, QGridLayout, QVBoxLayout, QTabWidget, QRadioButton, QButtonGroup, QSizePolicy
from PyQt5.QtGui import QIcon
from PyQt5 import QtWidgets, QtCore, QtGui
from PyQt5 import uic
import math
import sys
from gui.ui_tutorial import Ui_Tutorial
from gui.ui_aboutosdag import Ui_AboutOsdag
from gui.ui_ask_question import Ui_AskQuestion
from gui.ui_design_summary import Ui_DesignReport
from gui.LeftPanel_Button import Ui_LPButton
from gui.Submodule_Page import Ui_Submodule_Page
from gui.ui_OsdagMainPage import Ui_MainWindow
from gui.ExceptionDialog import CriticalExceptionDialog
# from design_type.connection.fin_plate_connection import design_report_show
# from design_type.connection.fin_plate_connection import DesignReportDialog
from design_type.connection.fin_plate_connection import FinPlateConnection
from design_type.connection.cleat_angle_connection import CleatAngleConnection
from design_type.connection.seated_angle_connection import SeatedAngleConnection
from design_type.connection.end_plate_connection import EndPlateConnection
from design_type.connection.base_plate_connection import BasePlateConnection
from design_type.connection.beam_cover_plate import BeamCoverPlate
from design_type.connection.beam_cover_plate_weld import BeamCoverPlateWeld
from design_type.connection.column_cover_plate_weld import ColumnCoverPlateWeld
from design_type.connection.beam_column_end_plate import BeamColumnEndPlate
from design_type.tension_member.tension_bolted import Tension_bolted
from design_type.tension_member.tension_welded import Tension_welded
from design_type.connection.beam_beam_end_plate_splice import BeamBeamEndPlateSplice
from design_type.connection.column_cover_plate import ColumnCoverPlate
from design_type.connection.column_end_plate import ColumnEndPlate
from design_type.compression_member.compression import Compression
#from design_type.tension_member.tension import Tension
# from cad.cad_common import call_3DBeam
import APP_CRASH.Appcrash.api as appcrash
import configparser
import os.path
import subprocess
if sys.platform == 'darwin':
print('its mac')
from gui.ui_template_for_mac import Ui_ModuleWindow
else:
from gui.ui_template import Ui_ModuleWindow
# from gui.ui_template import Ui_ModuleWindow
import io
import traceback
import time
class MyTutorials(QDialog):
def __init__(self, parent=None):
QDialog.__init__(self, parent)
self.ui = Ui_Tutorial()
self.ui.setupUi(self)
self.osdagmainwindow = parent
class MyAboutOsdag(QDialog):
def __init__(self, parent=None):
QDialog.__init__(self, parent)
self.ui = Ui_AboutOsdag()
self.ui.setupUi(self)
self.osdagmainwindow = parent
class MyAskQuestion(QDialog):
def __init__(self, parent=None):
QDialog.__init__(self, parent)
self.ui = Ui_AskQuestion()
self.ui.setupUi(self)
self.osdagmainwindow = parent
class New_Tab_Widget(QTabWidget): # Empty Custom Tab Widget
def __init__(self):
super().__init__()
#self.setTabShape(QTabWidget.Triangular)
class Submodule_Page(QWidget): # Module Varaints' page with a GridLayout and a Start Button
def __init__(self):
super().__init__()
self.ui=Ui_Submodule_Page()
self.ui.setupUi(self)
class Submodule_Widget(QWidget): # Module Variant widget with a Name, RadioButton and an Image
def __init__(self,Iterative,parent):
super().__init__()
Module_Name,Image_Path,Object_Name=Iterative
layout=QVBoxLayout()
self.setLayout(layout)
label=QLabel(Module_Name)
layout.addWidget(label)
label.setObjectName('module_name_label')
self.rdbtn=QRadioButton()
self.rdbtn.setObjectName(Object_Name)
self.rdbtn.setIcon(QIcon(Image_Path))
self.rdbtn.setIconSize(QSize(scale*300, scale*300))
layout.addWidget(self.rdbtn)
self.setSizePolicy(QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed))
class ModulePage(QWidget): # Empty Page with a layout
def __init__(self,margin=0):
super().__init__()
self.layout=QGridLayout()
self.setLayout(self.layout)
self.layout.setContentsMargins(0,0,0,0)
class LeftPanelButton(QWidget): # Custom Button widget for the Left Panel
def __init__(self,text):
super().__init__()
self.ui=Ui_LPButton()
self.ui.setupUi(self,scale)
self.ui.LP_Button.setText(text) #LP_Button is the QPushButton widget inside the LeftPanelButton Widget
class OsdagMainWindow(QMainWindow):
def __init__(self):
super().__init__()
resolution = QtWidgets.QDesktopWidget().screenGeometry()
width = resolution.width()
height = resolution.height()
self.ui=Ui_MainWindow()
self.ui.setupUi(self)
self.ui.switch.toggled.connect(self.change_theme)
self.ui.comboBox_help.currentIndexChanged.connect(self.selection_change)
self.ui.myStackedWidget.currentChanged.connect(self.current_changed)
self.Under_Development='UNDER DEVELOPMENT'
self.Modules={
'Connection' : {
'Shear Connection' : [
('Fin Plate','ResourceFiles/images/finplate.png','Fin_Plate'),
('Cleat Angle','ResourceFiles/images/cleatAngle.png','Cleat_Angle'),
('End Plate','ResourceFiles/images/endplate.png','End_Plate'),
('Seated Angle','ResourceFiles/images/seatedAngle1.png','Seated_Angle'),
self.show_shear_connection,
],
'Moment Connection' :{
'Beam-to-Beam Splice' :[
('Cover Plate Bolted','ResourceFiles/images/bbcoverplatebolted.png','B2B_Cover_Plate_Bolted'),
('Cover Plate Welded','ResourceFiles/images/bbcoverplatewelded.png','B2B_Cover_Plate_Welded'),
('End Plate', 'ResourceFiles/images/bb_splice.png', 'B2B_End_Plate_Splice'),
self.show_moment_connection,
],
'Beam-to-Column': [
('End Plate', 'ResourceFiles/images/BC-EBW_GUI.png','BC_End_Plate'),
self.show_moment_connection_bc
],
'Column-to-Column Splice' :[
('Cover Plate Bolted','ResourceFiles/images/cccoverplatebolted.png','C2C_Cover_Plate_Bolted'),
('Cover Plate Welded','ResourceFiles/images/cccoverplatewelded.png','C2C_Cover_Plate_Welded'),
('End Plate','ResourceFiles/images/ccep_flush.png','C2C_End_Plate_Connection'),
self.show_moment_connection_cc,
],
'PEB' : self.Under_Development,
},
'Base Plate':[
('Base Plate Connection', 'ResourceFiles/images/base_plate.png', 'Base_Plate'),
self.show_base_plate,
],
'Truss Connection' : self.Under_Development,
},
'Tension Member' : [
('Bolted to End Gusset','ResourceFiles/images/bolted_ten.png','Tension_Bolted'),
('Welded to End Gusset','ResourceFiles/images/welded_ten.png','Tension_Welded'),
self.show_tension_module,
],
'Compression Member' : self.Under_Development,
'Flexural Member' : self.Under_Development,
'Beam-Column' : self.Under_Development,
'Plate Girder' : self.Under_Development,
'Truss' : self.Under_Development,
'2D Frame' : self.Under_Development,
'3D Frame' : self.Under_Development,
'Group Design' : self.Under_Development,
}
####################################### UI Formation ################################
for ModuleName in self.Modules: #Level 1 dictionary handling
Button= LeftPanelButton(ModuleName)
self.ButtonConnection(Button,list(self.Modules.keys()),ModuleName)
self.ui.verticalLayout.addWidget(Button)
if(type(self.Modules[ModuleName])==dict): #level 2 dictionary handling
Page= ModulePage()
self.ui.myStackedWidget.addWidget(Page)
Current_Module=self.Modules[ModuleName]
Tab_Widget=New_Tab_Widget()
Page.layout.addWidget(Tab_Widget)
for Submodule in Current_Module:
if(type(Current_Module[Submodule])==dict): #Level 3 dictionary handling
New_Tab=ModulePage()
Tab_Widget.addTab(New_Tab,Submodule)
Sub_Page= ModulePage()
New_Tab.layout.addWidget(Sub_Page)
Current_SubModule=Current_Module[Submodule]
Sub_Tab_Widget=New_Tab_Widget()
Sub_Page.layout.addWidget(Sub_Tab_Widget)
for Sub_Sub_Module in Current_SubModule:
if(type(Current_SubModule[Sub_Sub_Module]) in [list,tuple]): # Final List/tuple Handling
New_Sub_Tab=Submodule_Page()
Sub_Tab_Widget.addTab(New_Sub_Tab,Sub_Sub_Module)
group=QButtonGroup(QWidget(Page))
row,col=0,0
n=math.floor((len(Current_SubModule[Sub_Sub_Module])-2)/2)
for Selection in Current_SubModule[Sub_Sub_Module][:-1]:
widget=Submodule_Widget(Selection,New_Sub_Tab)
group.addButton(widget.rdbtn)
New_Sub_Tab.ui.gridLayout.addWidget(widget,row,col)
if(col==n and len(Current_SubModule[Sub_Sub_Module])!=3):
row+=1
col=0
else:
col+=1
New_Sub_Tab.ui.StartButton.clicked.connect(Current_SubModule[Sub_Sub_Module][-1])
elif(Current_SubModule[Sub_Sub_Module]==self.Under_Development): # Final Under Development Handling
Sub_Tab_Widget.addTab(self.UnderDevelopmentModule(),Sub_Sub_Module)
else:
raise ValueError
elif(type(Current_Module[Submodule]) in [list,tuple]): #Level 3 list/tuple handling
New_Tab=Submodule_Page()
Tab_Widget.addTab(New_Tab,Submodule)
group=QButtonGroup(QWidget(Page))
row,col=0,0
n=math.floor((len(Current_Module[Submodule])-2)/2)
for Selection in Current_Module[Submodule][:-1]:
widget=Submodule_Widget(Selection,New_Tab)
group.addButton(widget.rdbtn)
New_Tab.ui.gridLayout.addWidget(widget,row,col)
if(col==n and len(Current_Module[Submodule])!=3):
row+=1
col=0
else:
col+=1
New_Tab.ui.StartButton.clicked.connect(Current_Module[Submodule][-1])
elif(Current_Module[Submodule]==self.Under_Development): #Level 3 Under Development handling
Tab_Widget.addTab(self.UnderDevelopmentModule(),Submodule)
else:
raise ValueError
elif(type(self.Modules[ModuleName]) in [list,tuple]): # Level 2 list/tuple handling
Page= Submodule_Page()
self.ui.myStackedWidget.addWidget(Page)
group=QButtonGroup(QWidget(Page))
row,col=0,0
n=math.floor((len(self.Modules[ModuleName])-2)/2)
for Selection in self.Modules[ModuleName][:-1]:
widget=Submodule_Widget(Selection,Page)
group.addButton(widget.rdbtn)
Page.ui.gridLayout.addWidget(widget,row,col)
if(col==n and len(self.Modules[ModuleName])!=3):
row+=1
col=0
else:
col+=1
Page.ui.StartButton.clicked.connect(self.Modules[ModuleName][-1])
elif(self.Modules[ModuleName]==self.Under_Development): #Level 2 Under Development handling
self.ui.myStackedWidget.addWidget(self.UnderDevelopmentModule())
else:
raise ValueError
self.resize(width * (0.85), height * (0.75))
self.center()
self.show()
def center(self):
frameGm = self.frameGeometry()
screen = QtWidgets.QApplication.desktop().screenNumber(QtWidgets.QApplication.desktop().cursor().pos())
centerPoint = QtWidgets.QApplication.desktop().screenGeometry(screen).center()
frameGm.moveCenter(centerPoint)
self.move(frameGm.topLeft())
@pyqtSlot(int)
def current_changed(self, index):
l = list(self.Modules.keys())
items = list(self.ui.verticalLayout.itemAt(i) for i in range(self.ui.verticalLayout.count()))
# print(items,"hfhh")
for item in range(len(items)):
if item == index-1:
items[item].widget().ui.LP_Button.setStyleSheet('''
background-color: qradialgradient(cx: 0.5, cy: 0.5, radius: 2, fx: 0.5, fy: 1, stop: 0 rgba(130, 36, 38,190), stop: 0.2 rgb(171, 39, 42), stop: 0.4 rgba(255,30,30,32));
''')
else:
items[item].widget().ui.LP_Button.setStyleSheet(";")
################################ UI Methods ###############################################
def closeEvent(self, event):
try:
sqlitepath = Path('ResourceFiles/Database/Intg_osdag.sqlite')
sqlpath = Path('ResourceFiles/Database/Intg_osdag.sql')
precisionscript = 'ResourceFiles/Database/precision.awk'
if sqlitepath.exists() and (
not sqlpath.exists() or sqlpath.stat().st_size == 0 or sqlpath.stat().st_mtime < sqlitepath.stat().st_mtime - 1):
sqlnewpath = Path('ResourceFiles/Database/Intg_osdag_new.sql')
cmd = 'sqlite3 ' + str(sqlitepath) + ' .dump | gawk -f ' + precisionscript + ' > ' + str(sqlnewpath)
error = os.system(cmd)
# if error != 0:
# raise Exception('SQLite conversion to SQL error 1')
# if sqlnewpath.stat().st_size == 0:
# raise Exception('SQLite conversion to SQL error 2')
os.remove(sqlpath)
sqlnewpath.rename(sqlpath)
sqlitepath.touch()
print('DUMP updated')
except Exception as e:
sqlnewpath.unlink()
print('Error: ', e)
def selection_change(self):
loc = self.ui.comboBox_help.currentText()
if loc == "Design Examples":
self.design_examples()
elif loc == "Video Tutorials":
self.open_tutorials()
elif loc == "About Osdag":
self.about_osdag()
elif loc == "Ask Us a Question":
self.ask_question()
elif loc == "Check for Update":
update_class = Update()
msg = update_class.notifi()
QMessageBox.information(self, 'Info',msg)
# elif loc == "FAQ":
# pass
def select_workspace_folder(self):
# This function prompts the user to select the workspace folder and returns the name of the workspace folder
config = configparser.ConfigParser()
config.read_file(open(r'Osdag.config'))
desktop_path = config.get("desktop_path", "path1")
folder = QFileDialog.getExistingDirectory(self, "Select Workspace Folder (Don't use spaces in the folder name)", desktop_path)
return folder
@staticmethod
def UnderDevelopmentModule():
Page= ModulePage()
label=QLabel('This Module is Currently Under Development')
Page.layout.addWidget(label)
label.setAlignment(Qt.AlignCenter)
label.setObjectName('under_development_label')
return Page
def ButtonConnection(self,Button,Modules,ModuleName):
Button.ui.LP_Button.clicked.connect(lambda : self.ui.myStackedWidget.setCurrentIndex(Modules.index(ModuleName)+1))
#################################### Module Launchers ##########################################
@pyqtSlot()
def show_shear_connection(self):
if self.findChild(QRadioButton,'Fin_Plate').isChecked():
self.hide()
self.ui2 = Ui_ModuleWindow(FinPlateConnection, ' ')
self.ui2.show()
self.ui2.closed.connect(self.show)
elif self.findChild(QRadioButton,'Cleat_Angle').isChecked():
self.hide()
self.ui2 = Ui_ModuleWindow(CleatAngleConnection, ' ')
self.ui2.show()
self.ui2.closed.connect(self.show)
elif self.findChild(QRadioButton,'Seated_Angle').isChecked():
self.hide()
self.ui2 = Ui_ModuleWindow( SeatedAngleConnection, ' ')
self.ui2.show()
self.ui2.closed.connect(self.show)
elif self.findChild(QRadioButton,'End_Plate').isChecked():
self.hide()
self.ui2 = Ui_ModuleWindow(EndPlateConnection, ' ')
self.ui2.show()
self.ui2.closed.connect(self.show)
else:
QMessageBox.about(self, "INFO", "Please select appropriate connection")
def show_moment_connection(self):
if self.findChild(QRadioButton,'B2B_Cover_Plate_Bolted').isChecked():
self.hide()
self.ui2 = Ui_ModuleWindow(BeamCoverPlate, ' ')
self.ui2.show()
self.ui2.closed.connect(self.show)
elif self.findChild(QRadioButton,'B2B_Cover_Plate_Welded').isChecked():
self.hide()
self.ui2 = Ui_ModuleWindow(BeamCoverPlateWeld, ' ')
self.ui2.show()
self.ui2.closed.connect(self.show)
# elif self.findChild(QRadioButton,'B2B_End_Plate_Connection').isChecked():
# self.hide()
# self.ui2 = Ui_ModuleWindow(BeamBeamEndPlateSplice,' ')
# self.ui2.show()
# self.ui2.closed.connect(self.show)
elif self.findChild(QRadioButton, 'B2B_End_Plate_Splice').isChecked():
self.hide()
self.ui2 = Ui_ModuleWindow(BeamBeamEndPlateSplice, ' ')
self.ui2.show()
self.ui2.closed.connect(self.show)
def show_moment_connection_bc(self):
if self.findChild(QRadioButton,'BC_End_Plate').isChecked():
self.hide()
self.ui2 = Ui_ModuleWindow(BeamColumnEndPlate, ' ')
self.ui2.show()
self.ui2.closed.connect(self.show)
def show_base_plate(self):
if self.findChild(QRadioButton, 'Base_Plate').isChecked():
self.hide()
self.ui2 = Ui_ModuleWindow(BasePlateConnection, ' ')
self.ui2.show()
self.ui2.closed.connect(self.show)
def show_moment_connection_cc(self):
if self.findChild(QRadioButton,'C2C_Cover_Plate_Bolted').isChecked() :
self.hide()
self.ui2 = Ui_ModuleWindow(ColumnCoverPlate, ' ')
self.ui2.show()
self.ui2.closed.connect(self.show)
elif self.findChild(QRadioButton,'C2C_Cover_Plate_Welded').isChecked():
self.hide()
self.ui2 = Ui_ModuleWindow(ColumnCoverPlateWeld, ' ')
self.ui2.show()
self.ui2.closed.connect(self.show)
elif self.findChild(QRadioButton,'C2C_End_Plate_Connection').isChecked():
self.hide()
self.ui2 = Ui_ModuleWindow(ColumnEndPlate, ' ')
self.ui2.show()
self.ui2.closed.connect(self.show)
def show_compression_module(self):
# folder = self.select_workspace_folder()
# folder = str(folder)
# if not os.path.exists(folder):
# if folder == '':
# pass
# else:
# os.mkdir(folder, 0o755)
#
# root_path = folder
# images_html_folder = ['images_html']
# flag = True
# for create_folder in images_html_folder:
# if root_path == '':
# flag = False
# return flag
# else:
# try:
# os.mkdir(os.path.join(root_path, create_folder))
# except OSError:
# shutil.rmtree(os.path.join(folder, create_folder))
# os.mkdir(os.path.join(root_path, create_folder))
if self.findChild(QRadioButton,'Compression_Bolted').isChecked():
self.hide()
self.ui2 = Ui_ModuleWindow(Compression, ' ')
self.ui2.show()
self.ui2.closed.connect(self.show)
elif self.findChild(QRadioButton,'Compression_Welded').isChecked():
self.hide()
self.ui2 = Ui_ModuleWindow(Compression, ' ')
self.ui2.show()
self.ui2.closed.connect(self.show)
def show_tension_module(self):
# folder = self.select_workspace_folder()
# folder = str(folder)
# if not os.path.exists(folder):
# if folder == '':
# pass
# else:
# os.mkdir(folder, 0o755)
#
# root_path = folder
# images_html_folder = ['images_html']
# flag = True
# for create_folder in images_html_folder:
# if root_path == '':
# flag = False
# return flag
# else:
# try:
# os.mkdir(os.path.join(root_path, create_folder))
# except OSError:
# shutil.rmtree(os.path.join(folder, create_folder))
# os.mkdir(os.path.join(root_path, create_folder))
if self.findChild(QRadioButton,'Tension_Bolted').isChecked():
self.hide()
self.ui2 = Ui_ModuleWindow(Tension_bolted, ' ')
self.ui2.show()
self.ui2.closed.connect(self.show)
elif self.findChild(QRadioButton,'Tension_Welded').isChecked():
self.hide()
self.ui2 = Ui_ModuleWindow(Tension_welded, ' ')
self.ui2.show()
self.ui2.closed.connect(self.show)
################################# Help Actions ############################################
def about_osdag(self):
dialog = MyAboutOsdag(self)
dialog.show()
def open_osdag(self):
self.about_osdag()
def tutorials(self):
dialog = MyTutorials(self)
dialog.show()
def open_tutorials(self):
self.tutorials()
def ask_question(self):
dialog = MyAskQuestion(self)
dialog.show()
def open_question(self):
self.ask_question()
def design_examples(self):
root_path = os.path.join('ResourceFiles', 'html_page', '_build', 'html')
for html_file in os.listdir(root_path):
# if html_file.startswith('index'):
print(os.path.splitext(html_file)[1])
if os.path.splitext(html_file)[1] == '.html':
if sys.platform == ("win32" or "win64"):
os.startfile(os.path.join(root_path, html_file))
else:
opener ="open" if sys.platform == "darwin" else "xdg-open"
subprocess.call([opener, "%s/%s" % (root_path, html_file)])
def change_theme(self):
state = self.ui.switch.isChecked()
toggle_stylesheet(state)
# class SystemTrayIcon(QtWidgets.QSystemTrayIcon):
#
# def __init__(self, icon, parent=None):
# QtWidgets.QSystemTrayIcon.__init__(self, icon, parent)
# self.parent = parent
# menu = QtWidgets.QMenu(self.parent)
# self.setContextMenu(menu)
# menu.addAction("Exit", self.exit)
#
#
# def exit(self):
# QCoreApplication.exit()
######################### UpDateNotifi ################
# class Update(QMainWindow):
# def __init__(self, old_version):
# super().__init__()
# self.old_version=old_version
# def notifi(self):
# try:
# url = "https://anshulsingh-py.github.io/test/version.txt"
# file = urllib.request.urlopen(url)
# for line in file:
# decoded_line = line.decode("utf-8")
# new_version = decoded_line.split("=")[1]
# if int(new_version) > self.old_version:
# print("update")
# msg = QMessageBox.information(self, 'Update available','<a href=https://google.com>Click to downlaod<a/>')
# except:
# print("No internet connection")
def toggle_stylesheet(state):
app = QApplication.instance()
if app is None:
raise RuntimeError("No Qt Application found.")
if state:
path = 'darkstyle.qss'
else:
path = 'light.qss'
theme_path = os.path.join(os.path.dirname(__file__), 'themes', path)
file = QFile(theme_path)
file.open(QFile.ReadOnly | QFile.Text)
stream = QTextStream(file)
app.setStyleSheet(stream.readAll())
def hook_exception(exc_type, exc_value, tracebackobj):
instance = QApplication.instance()
# KeyboardInterrupt is a special case.
# We don't raise the error dialog when it occurs.
if issubclass(exc_type, KeyboardInterrupt):
if instance:
instance.closeAllWindows()
return
separator = '-' * 80
notice = \
"""An unhandled exception occurred. Please report the problem\n""" \
"""using the error reporting dialog or raise the issue to {}.\n""" \
"""\n\nError information:\n""".format('github.com/osdag-admin/Osdag')
time_string = time.strftime("%Y-%m-%d, %H:%M:%S")
tbinfofile = io.StringIO()
traceback.print_tb(tracebackobj, None, tbinfofile)
tbinfofile.seek(0)
tbinfo = tbinfofile.read()
errmsg = '%s: \n%s' % (str(exc_type), str(exc_value))
sections = [separator, time_string, separator, errmsg, separator, tbinfo]
msg = '\n'.join(sections)
error_box.text_edit.setText(str(notice) + str(msg))
error_box.titlebar.save_log.clicked.connect(save_log(str(notice)+str(msg)))
error_box.titlebar.report_issue.clicked.connect(send_crash_report)
error_box.setWindowModality(QtCore.Qt.ApplicationModal)
if not error_box.exec_():
instance.quit()
def save_log(log):
def save_():
file_type = "log (*.log)"
filename, _ = QFileDialog.getSaveFileName(QFileDialog(), "Save File As", '', file_type)
if filename:
with open(filename,'w') as file:
file.write(log)
QMessageBox.information(QMessageBox(), "Information", "Log saved successfully.")
return save_
def get_system_info():
return 'OS: %s\nPython: %r' % (sys.platform, sys.version_info)
def get_application_log():
return error_box.text_edit.toPlainText()
def send_crash_report():
appcrash.get_application_log = get_application_log
appcrash.get_system_information = get_system_info
appcrash.show_report_dialog()
class SystemTrayIcon(QtWidgets.QSystemTrayIcon):
def __init__(self, icon, parent=None):
QtWidgets.QSystemTrayIcon.__init__(self, icon, parent)
self.parent = parent
menu = QtWidgets.QMenu(self.parent)
self.setContextMenu(menu)
menu.addAction("Exit", self.exit)
def exit(self):
QCoreApplication.exit()
if __name__ == '__main__':
# from cad.common_logic import CommonDesignLogic
from multiprocessing import Pool
import multiprocessing
# app = QApplication(sys.argv)
# screen = app.screens()[0]
# dpi = screen.physicalDotsPerInch()
# scale = round(dpi/140.0,1)
#
# print('scale', dpi, scale,scale*300)
path = os.path.join(os.path.dirname(__file__), 'themes', 'light.qss')
file = QFile(path)
file.open(QFile.ReadOnly | QFile.Text)
stream = QTextStream(file)
app = QApplication(sys.argv)
app.setStyleSheet(stream.readAll())
app.setStyle('Fusion')
# path = os.path.join(os.path.dirname(__file__), 'ResourceFiles', 'images', 'Osdag.png')
window = OsdagMainWindow()
# trayIcon = SystemTrayIcon(QtGui.QIcon(path), window)
############################ Exception Dialog and Error Reporting ###################
error_box = CriticalExceptionDialog()
GITHUB_OWNER = 'osdag-admin' # username of the github account where crash report is to be submitted
GITHUB_REPO = 'Osdag' # repo name
EMAIL = '[email protected]' # Email address of developers
appcrash.install_backend(appcrash.backends.GithubBackend(GITHUB_OWNER, GITHUB_REPO))
appcrash.install_backend(appcrash.backends.EmailBackend(EMAIL, 'Osdag'))
#my_settings = QtCore.QSettings('FOSSEE','osdag')
#appcrash.set_qsettings(my_settings)
'''
You can save your GitHub username and password across each sessions so that you don't have to enter it each time you report an issue.
Simply uncomment above two lines. To use QSetings we need to give an organisation name and the application name (compulsory).
For example, 'FOSSEE' is an organisation name and 'Osdag' is the application name in the above QSettings. Feel free to change them to suit your requirement, but try to keep it constant.
Do not change it frequently.
'''
############################ Exception Dialog and Error Reporting ###################
# trayIcon.show()
try:
# window.notification2()
#update = Update(0)
#update.notifi()
sys.excepthook = hook_exception
QCoreApplication.exit(app.exec_()) # to properly close the Qt Application use QCoreApplication instead of sys
except BaseException as e:
print("ERROR", e)