'''
template version: utt.Class_1010_20200615
ClassName:
  * description
  
v0.1:
  * base functions

'''
# ---- base lib 2020.02.13----
import os,sys
# ---- pyMode 2020.02.13----
# python 2,3 support unicode function
try:
    UNICODE_EXISTS = bool(type(unicode))
except NameError:
    # unicode = lambda s: str(s) # this works for function but not for class check
    unicode = str
if sys.version_info[:3][0]>=3:
    import importlib
    reload = importlib.reload # add reload

pyMode = '.'.join([ str(n) for n in sys.version_info[:3] ])
print("Python: {0}".format(pyMode))
# ---- qtMode 2020.02.13 ----
qtMode = 0 # 0: PySide; 1 : PyQt, 2: PySide2, 3: PyQt5
qtModeList = ('PySide', 'PyQt4', 'PySide2', 'PyQt5')
try:
    from PySide import QtGui, QtCore
    import PySide.QtGui as QtWidgets
    qtMode = 0
except ImportError:
    try:
        from PySide2 import QtCore, QtGui, QtWidgets
        qtMode = 2
    except ImportError:
        try:
            from PyQt4 import QtGui,QtCore
            import PyQt4.QtGui as QtWidgets
            import sip
            qtMode = 1
        except ImportError:
            from PyQt5 import QtGui,QtCore,QtWidgets
            import sip
            qtMode = 3
print('Qt: {0}'.format(qtModeList[qtMode]))
# ---- user lib ----

class ClassName(QtWidgets.QWidget):
    def __init__(self, parent=None,mode=0):
        QtWidgets.QWidget.__init__(self,parent)
        # memo
        self.parent=parent
        
        self.memoData={}
        self.memoData['last_import']=''
        self.memoData['last_export']=''
        self.memoData['last_browse']=''
        # UI
        self.uiList={}
        self.uiList['main_layout']=QtWidgets.QHBoxLayout();
        self.uiList['main_layout'].setContentsMargins(0, 0, 0, 0)
        self.setLayout(self.uiList['main_layout'])
        
        self.qui('main_label;Example | main_input', 'main_layout')
        self.qui_policy('main_input',5,3)
        
        # hide ui
        
        # connect UI
        self.Establish_Connections()
    def Establish_Connections(self):
        for ui_name in self.uiList.keys():
            prefix = ui_name.rsplit('_', 1)[0]
            if ui_name.endswith('_btn'):
                if hasattr(self, prefix+"_action"):
                    self.uiList[ui_name].clicked.connect(getattr(self, prefix+"_action"))
        # drop support
        self.uiList['main_input'].installEventFilter(self)
    
    def eventFilter(self, object, event):
        # the main window event filter function
        if event.type() == QtCore.QEvent.DragEnter:
            data = event.mimeData()
            urls = data.urls()
            if object is self.uiList['main_input'] and (urls and urls[0].scheme() == 'file'):
                event.acceptProposedAction()
            return 1
        elif event.type() == QtCore.QEvent.Drop:
            data = event.mimeData()
            urls = data.urls()
            if object is self.uiList['main_input'] and (urls and urls[0].scheme() == 'file'):
                filePath = unicode(urls[0].path())[1:]
                self.uiList['main_input'].setText(os.path.normpath(filePath))
                
            return 1
        return 0
        
    # ---- user functions ----
    
    # ---- core functions ----
    def ___core_functions___(self):
        pass
    def qui_menu(self, action_list_str, menu_str):
        # qui menu creation
        # syntax: self.qui_menu('right_menu_createFolder_atn;Create Folder,Ctrl+D | right_menu_openFolder_atn;Open Folder', 'right_menu')
        if menu_str not in self.uiList.keys():
            self.uiList[menu_str] = QtWidgets.QMenu()
        create_opt_list = [ x.strip() for x in action_list_str.split('|') ]
        for each_creation in create_opt_list:
            ui_info = [ x.strip() for x in each_creation.split(';') ]
            atn_name = ui_info[0]
            atn_title = ''
            atn_hotkey = ''
            if len(ui_info) > 1:
                options = ui_info[1].split(',')
                atn_title = '' if len(options) < 1 else options[0]
                atn_hotkey = '' if len(options) < 2 else options[1]
            if atn_name != '':
                if atn_name == '_':
                    self.uiList[menu_str].addSeparator()
                else:
                    if atn_name not in self.uiList.keys():
                        self.uiList[atn_name] = QtWidgets.QAction(atn_title, self)
                        if atn_hotkey != '':
                            self.uiList[atn_name].setShortcut(QtGui.QKeySequence(atn_hotkey))
                    self.uiList[menu_str].addAction(self.uiList[atn_name])
    def default_menu_call(self, ui_name, point):
        if ui_name in self.uiList.keys() and ui_name+'_menu' in self.uiList.keys():
            self.uiList[ui_name+'_menu'].exec_(self.uiList[ui_name].mapToGlobal(point))
    def qui(self, ui_str, layout_str):
        ui_str_list = [x.strip() for x in ui_str.split('|') if x.strip()]
        ui_list = []
        for ui in ui_str_list:
            ui_option = ''
            if ';' in ui:
                ui,ui_option = ui.split(';',1)
            if ui not in self.uiList.keys():
                # creation process
                if ui.endswith('_choice'):
                    self.uiList[ui]= QtWidgets.QComboBox()
                elif ui.endswith('_input'):
                    self.uiList[ui]= QtWidgets.QLineEdit()
                elif ui.endswith('_txt'):
                    self.uiList[ui]= QtWidgets.QTextEdit()
                elif ui.endswith('_label'):
                    self.uiList[ui]= QtWidgets.QLabel(ui_option)
                elif ui.endswith('_btn'):
                    self.uiList[ui]= QtWidgets.QPushButton(ui_option)
                elif ui.endswith('_check'):
                    self.uiList[ui]= QtWidgets.QCheckBox(ui_option)
                elif ui.endswith('_spin'):
                    self.uiList[ui]= QtWidgets.QSpinBox()
                    if len(ui_option)>0:
                        int_list = ui_option.replace('(','').replace(')','').split(',')
                        self.uiList[ui].setMaximum(10000) # override default 99
                        if len(int_list)>0 and int_list[0].isdigit():
                            self.uiList[ui].setValue(int(int_list[0]))
                        if len(int_list)>1 and int_list[1].isdigit():
                            self.uiList[ui].setMinimum(int(int_list[1]))
                        if len(int_list)>2 and int_list[2].isdigit():
                            self.uiList[ui].setMaximum(int(int_list[2]))
                elif ui.endswith('_tree'):
                    self.uiList[ui] = QtWidgets.QTreeWidget()
                    if len(ui_option)>0:
                        label_list = ui_option.replace('(','').replace(')','').split(',')
                        self.uiList[ui].setHeaderLabels(label_list)
                elif ui.endswith('_space'):
                    self.uiList[ui] = QtWidgets.QSpacerItem(5,5, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Preferred )
                else:
                    # creation fail
                    continue
            # collect existing ui and created ui
            ui_list.append(ui)
        layout_option = ''
        if ';' in layout_str:
            layout_str, layout_option = layout_str.split(';',1)
        if layout_str not in self.uiList.keys():
            # try create layout
            if layout_str.endswith('_grp'):
                # grp option
                grp_option = layout_option.split(';',1)
                grp_title = layout_str
                if len(grp_option)>0:
                    if grp_option[0]=='vbox':
                        self.uiList[layout_str+'_layout'] = QtWidgets.QVBoxLayout()
                    elif grp_option[0]=='hbox':
                        self.uiList[layout_str+'_layout'] = QtWidgets.QHBoxLayout()
                if len(grp_option) == 2:
                    grp_title = grp_option[1]
                self.uiList[layout_str] = QtWidgets.QGroupBox(grp_title)
                self.uiList[layout_str].setLayout(self.uiList[layout_str+'_layout'])
                # pass grp layout
                layout_str = layout_str+'_layout'
            else:
                if layout_option == 'vbox':
                    self.uiList[layout_str] = QtWidgets.QVBoxLayout()
                elif layout_option == 'hbox':
                    self.uiList[layout_str] = QtWidgets.QHBoxLayout()
                else:
                    return
        cur_layout = self.uiList[layout_str]
        if not isinstance(cur_layout, QtWidgets.QBoxLayout):
            return
        for ui in ui_list:
            ui_option = ''
            if ';' in ui:
                ui,ui_option = ui.split(';',1)
            if isinstance(self.uiList[ui], QtWidgets.QWidget):
                cur_layout.addWidget(self.uiList[ui])
            elif isinstance(self.uiList[ui], QtWidgets.QSpacerItem):
                cur_layout.addItem(self.uiList[ui])
            elif isinstance(self.uiList[ui], QtWidgets.QLayout):
                cur_layout.addLayout(self.uiList[ui])
    def quickMsg(self, msg, block=1, ask=0):
        tmpMsg = QtWidgets.QMessageBox(self) # for simple msg that no need for translation
        tmpMsg.setWindowTitle("Info")
        lineCnt = len(msg.split('\n'))
        if lineCnt > 25:
            scroll = QtWidgets.QScrollArea()
            scroll.setWidgetResizable(1)
            content = QtWidgets.QWidget()
            scroll.setWidget(content)
            layout = QtWidgets.QVBoxLayout(content)
            tmpLabel = QtWidgets.QLabel(msg)
            tmpLabel.setTextInteractionFlags(QtCore.Qt.TextSelectableByMouse)
            layout.addWidget(tmpLabel)
            tmpMsg.layout().addWidget(scroll, 0, 0, 1, tmpMsg.layout().columnCount())
            tmpMsg.setStyleSheet("QScrollArea{min-width:600 px; min-height: 400px}")
        else:
            tmpMsg.setText(msg)
        if block == 0:
            tmpMsg.setWindowModality( QtCore.Qt.NonModal )
        if ask==0:
            tmpMsg.addButton("OK",QtWidgets.QMessageBox.YesRole)
        else:
            tmpMsg.setStandardButtons(QtWidgets.QMessageBox.Ok | QtWidgets.QMessageBox.Cancel)
        if block:
            value = tmpMsg.exec_()
            if value == QtWidgets.QMessageBox.Ok:
                return 1
            else:
                return 0
        else:
            tmpMsg.show()
            return 0
    def quickInfo(self, info, force=0):
        if hasattr( self.window(), "quickInfo") and force == 0:
            self.window().statusBar().showMessage(info)
    def qui_policy(self, ui_list, w, h):
        # reference value
        policyList = ( 
            QtWidgets.QSizePolicy.Fixed, 
            QtWidgets.QSizePolicy.Minimum, 
            QtWidgets.QSizePolicy.Maximum, 
            QtWidgets.QSizePolicy.Preferred, 
            QtWidgets.QSizePolicy.Expanding, 
            QtWidgets.QSizePolicy.MinimumExpanding, 
            QtWidgets.QSizePolicy.Ignored,
        )
        # 0 = fixed; 1 > min; 2 < max; 3 = prefered; 4 = <expanding>; 5 = expanding> Aggresive; 6=4 ignored size input
        if not isinstance(ui_list, (list, tuple)):
            ui_list = [ui_list]
        for each_ui in ui_list:
            if isinstance(each_ui, str):
                each_ui = self.uiList[each_ui]
            each_ui.setSizePolicy(policyList[w],policyList[h])
    def quickModKeyAsk(self):
        modifiers = QtWidgets.QApplication.queryKeyboardModifiers()
        clickMode = 0 # basic mode
        if modifiers == QtCore.Qt.ControlModifier:
            clickMode = 1 # ctrl
        elif modifiers == QtCore.Qt.ShiftModifier:
            clickMode = 2 # shift
        elif modifiers == QtCore.Qt.AltModifier:
            clickMode = 3 # alt
        elif modifiers == QtCore.Qt.ControlModifier | QtCore.Qt.ShiftModifier | QtCore.Qt.AltModifier:
            clickMode = 4 # ctrl+shift+alt
        elif modifiers == QtCore.Qt.ControlModifier | QtCore.Qt.AltModifier:
            clickMode = 5 # ctrl+alt
        elif modifiers == QtCore.Qt.ControlModifier | QtCore.Qt.ShiftModifier:
            clickMode = 6 # ctrl+shift
        elif modifiers == QtCore.Qt.AltModifier | QtCore.Qt.ShiftModifier:
            clickMode = 7 # alt+shift
        return clickMode
class TestWin(QtWidgets.QMainWindow):
    def __init__(self):
        QtWidgets.QMainWindow.__init__(self)
        main_widget = QtWidgets.QWidget()
        self.setCentralWidget(main_widget)
        
        main_layout = QtWidgets.QVBoxLayout()
        main_widget.setLayout(main_layout)

def main():
    app = QtWidgets.QApplication(sys.argv)
    main_win = ClassName()
    main_win.show()
    sys.exit(app.exec_())
    
if __name__ == "__main__":
    main()