try:from pymxs import runtime as rt 
except:pass
if (rt.maxversion())[7] < 2026:
    from PySide2.QtWidgets import (
        QApplication, QDialog, QVBoxLayout, QHBoxLayout, QLabel, QLineEdit, QComboBox, QDateEdit, QPushButton,
        QGroupBox, QTableWidget, QTableWidgetItem, QFileDialog, QTextEdit, QSpinBox, QDoubleSpinBox, QScrollArea,
        QWidget, QMainWindow, QTabWidget, QMessageBox
    )
    from PySide2.QtCore import Qt, QDate, QThread, Signal,  QDateTime
    from PySide2.QtGui import QPixmap, QTextCursor
else:
    from PySide6.QtWidgets import (
        QApplication, QDialog, QVBoxLayout, QHBoxLayout, QLabel, QLineEdit, QComboBox, QDateEdit, QPushButton,
        QGroupBox, QTableWidget, QTableWidgetItem, QFileDialog, QTextEdit, QSpinBox, QDoubleSpinBox, QScrollArea,
        QWidget, QMainWindow, QTabWidget, QMessageBox
    )
    from PySide6.QtCore import Qt, QDate, QThread, Signal,  QDateTime
    from PySide6.QtGui import QPixmap, QTextCursor
import time
import json
import tempfile, os # temp dosyasina erismek dosya olusturmak icin
import mimetypes
import http.client
from codecs import encode
import xml.etree.ElementTree as et # xml dosyalarini okumak icin
import pandas as pd # excel dosyalarini okumak icin

local_en = {
    "mainDialog": {
        "windowTitle":"JLSF Product Management",
        "header":{
            "title":"Upload Product",
            "login":["Username: ","Password: ","Log In","Log Out"],
            "querybox":["Log in Succesfully", "Log in Failed","Log Out Succesfully"]
        },
        "databaseInformation": {
            "groupBoxTitle":"Database Information",
            "labelList":["Made Type:","Category:", "ddnum", "psize", "SKU JS","*SKU OP:","SKU ERP:","Design Date:"],
            "madeTypeList":["Original", "Update", "Replace", "Custom",],
        },
        "productParameters":{
        "groupBoxTitle":"Product Parameters",
        "labelList":["Dimension:","Materials:","Colour:","Thickness","Author:"],
        },
        "imageUploads":{
            "groupBoxTitle":"Product Images",
            "imgTitles":["Main", "Appearance", "Structure", "Line Drawing", "Official", "Hole Site"]
        },
        "packageParameters":{
            "groupBoxTitle":"Package Parameters",
            "labelList":["Width:","Length:","Height:","Weight:","Filler Area:"]
        },
        "additionalAccesories":{
            "groupBoxTitle":"Additional Accessories",
            "labelList":["Accessory Name","Model","Quantity","Actions"]
        },
        "excelFile":{
            "groupBoxTitle":"Excel File",
            "loadexcel_btn":"Select Excel File",
            "clear_btn":"Clear Data"
        },
        "xmlFile":{
            "groupBoxTitle":"Xml File",
            "loadxml_btn":"Select Xml File",
            "clear_btn":"Clear Data"
        },
        "bottomSection":{
            "productid_label":"Product ID:",
            "update_btn":"Save",
            "update_btn_querybox":["Product ID: ","Do you want continue?"],
            "create_btn":"Create New Product",
            "create_btn_querybox":"Are you sure to create a new product?"
        }
    },
    "processDialog": {
        "windowTitle":"JLSF Product Management",
        "log":{
            "productUpdate":"Product Update",
            "idNumber":"ID Number: ",
            "jsName":"JS Name: ",
            "creatingNewProduct":"Creating New Product..",
            "startUploading":"Start Uploading...",
            "imagesUploading":"Images Uploading...",
            "imagePathManuallyDefined":"Image Path Manually Defined:",
            "imageUploadSuccess":"Image Upload Success:",
            "imageUploadFailed":"Image Upload Failed: ",
            "imageUpdateError":"Image Update ERROR!",
            "newProductID":"New Product ID: ",
            "productUploadError":"Product Upload ERROR!",
            "xmlFileUploadError":"Xml File Upload ERROR!",
            "time":["Elapsed "," seconds"],
            "dataUpdateError":"Data Update ERROR! -- Check Server Connection or Log in Again",
            "logFileSaveError":"Failed to Save Log File!"
        },
        "close_btn":"Close",
        "clear_btn":"Clear Log",
        "clear_btn_message":"Are you sure to clear the log file?"
    }
}
local_ch = {
    "mainDialog": {
        "windowTitle": "JLSF 产品管理",
        "header": {
            "title": "上传产品",
            "login": ["用户名: ", "密码: ", "登录", "退出登录"],
            "querybox": ["登录成功", "登录失败", "退出登录成功"]
        },
        "databaseInformation": {
            "groupBoxTitle": "数据库信息",
            "labelList": ["制作类型:", "分类:", "DD编号", "产品尺寸", "SKU JS", "*SKU OP:", "SKU ERP:", "设计日期:"],
            "madeTypeList": ["原创", "更新", "替换", "定制"]
        },
        "productParameters": {
            "groupBoxTitle": "产品参数",
            "labelList": ["尺寸:", "材料:", "颜色:", "厚度", "作者:"]
        },
        "imageUploads": {
            "groupBoxTitle": "产品图片",
            "imgTitles": ["主图", "外观", "结构", "线稿", "官方图", "孔位图"]
        },
        "packageParameters": {
            "groupBoxTitle": "包装参数",
            "labelList": ["宽度:", "长度:", "高度:", "重量:", "填充区域:"]
        },
        "additionalAccesories": {
            "groupBoxTitle": "附加配件",
            "labelList": ["配件名称", "型号", "数量", "操作"]
        },
        "excelFile": {
            "groupBoxTitle": "Excel 文件",
            "loadexcel_btn": "选择 Excel 文件",
            "clear_btn": "清除数据"
        },
        "xmlFile": {
            "groupBoxTitle": "Xml 文件",
            "loadxml_btn": "选择 Xml 文件",
            "clear_btn": "清除数据"
        },
        "bottomSection": {
            "productid_label": "产品ID:",
            "update_btn": "保存",
            "update_btn_querybox":["产品 ID: ","您想继续吗?"],
            "create_btn": "创建新产品",
            "create_btn_querybox":"您确定要创建新产品吗?"
        }
    },
    "processDialog": {
        "windowTitle": "景瓴十方产品管理",
        "log": {
            "productUpdate": "产品更新",
            "idNumber": "ID: ",
            "jsName": "简尚货号: ",
            "creatingNewProduct": "创建新产品中..",
            "startUploading": "开始上传...",
            "imagesUploading": "图片上传中...",
            "imagePathManuallyDefined": "图片路径已手动定义:",
            "imageUploadSuccess": "图片上传成功:",
            "imageUploadFailed": "图片上传失败: ",
            "imageUpdateError": "图片更新错误!",
            "newProductID": "新产品ID: ",
            "productUploadError": "产品上传错误!",
            "xmlFileUploadError": "Xml 文件上传错误!",
            "time": ["耗时 ", " 秒"],
            "dataUpdateError": "数据更新错误! -- 请检查服务器连接并重新登录。",
            "logFileSaveError": "保存日志文件失败!"
        },
        "close_btn": "关闭",
        "clear_btn": "清除日志",
        "clear_btn_message": "确定要清除日志文件吗?"
    }
}

rt.execute('sarfcurrentlocalization = getinisetting sarfinet.inifile "Settings" "Localization"')
localization = local_en
if rt.sarfcurrentlocalization == "en-us.ms":localization = local_en
elif rt.sarfcurrentlocalization == "zh-cn.ms":localization = local_ch
# localization = local_en
# localization = local_ch

categorylistjson = json.dumps([
    {"id":1,"category":"\u6d4b\u8bd5-\u54c1\u7c7b","serial_number":"cs"},
    {"id":2,"category":"\u978b\u67dc","serial_number":"1X"},
    {"id":3,"category":"\u4e66\u67dc","serial_number":"1S"},
    {"id":4,"category":"\u9910\u8fb9\u67dc","serial_number":"1C"},
    {"id":5,"category":"\u4e66\u67b6","serial_number":"2S"},
    {"id":6,"category":"\u68b3\u5986\u53f0","serial_number":"3S"},
    {"id":7,"category":"\u6597\u67dc","serial_number":"1O"},
    {"id":8,"category":"\u5e8a\u5934\u67dc","serial_number":"1T"},
    {"id":9,"category":"\u98d8\u7a97\u67dc","serial_number":"1P"},
    {"id":10,"category":"\u89d2\u51e0\u8fb9\u51e0","serial_number":""},
    {"id":12,"category":"\u589e\u9ad8\u67b6","serial_number":""},
    {"id":13,"category":"\u684c\u4e0a\u67b6","serial_number":""},
    {"id":14,"category":"\u7f6e\u7269\u67b6","serial_number":""},
    {"id":15,"category":"\u7095\u51e0","serial_number":""},
    {"id":16,"category":"\u7535\u8111\u684c","serial_number":""},
    {"id":17,"category":"\u7535\u89c6\u67dc","serial_number":""},
    {"id":18,"category":"\u9910\u684c","serial_number":""},
    {"id":19,"category":"\u4e66\u684c","serial_number":""},
    {"id":20,"category":"\u6a71\u67dc","serial_number":""},
    {"id":21,"category":"\u5ba0\u7269\u5bb6\u5177","serial_number":""},
    {"id":22,"category":"\u8fb9\u67dc","serial_number":"1B"},
    {"id":23,"category":"\u6362\u978b\u51f3","serial_number":"1H"},
    {"id":24,"category":"\u7384\u5173\u684c","serial_number":""},
    {"id":25,"category":"\u6587\u4ef6\u67dc","serial_number":"WJ"},
    {"id":26,"category":"\u8863\u67dc","serial_number":"1Y"},
    {"id":27,"category":"\u978b\u67b6","serial_number":""},
    {"id":28,"category":"\u7384\u5173\u67dc","serial_number":"2X"},
    {"id":29,"category":"\u8336\u5427","serial_number":"CB"},
    {"id":30,"category":"\u5199\u5b57\u53f0","serial_number":"XZ"},
    {"id":31,"category":"\u5c42\u67dc","serial_number":"CG"},
    {"id":32,"category":"\u62bd\u5c49\u67dc","serial_number":"CTIG"},
    {"id":33,"category":"\u8336\u51e0","serial_number":""},
    {"id":34,"category":"\u529e\u516c\u684c","serial_number":"BGZ"},
    {"id":35,"category":"\u9152\u67dc","serial_number":"JG"}
    ])
categorylist = json.loads(categorylistjson)
data = {
    "product_id": "1",
    "main": {
        "name": "测试商品",
        "category_id": "衣柜",
        "sku_js": "js081423",
        "sku_op": "yy08123",
        "sku_erp": "erp081432",
        "madetype": "O", # U = UPDATE, O = ORIGINAL, C = CUSTOM MADE, P = REPLACE
        "ddnum": 1,
        "psize": 1,
        "scale": "1200*800*600",
        "material": "刨花板",
        "color": "暖白",
        "thickness": 2,
        "is_sub_pkg": "1",
        "pkg_length": 0,
        "pkg_width": 0,
        "pkg_height": 0,
        "pkgs": [
            {
                "pkg_length": 1200,
                "pkg_width": 700,
                "pkg_height": 800,
                "hardware_weight": 1.2,
                "filler_area":0
            },
            {
                "pkg_length": 1300,
                "pkg_width": 800,
                "pkg_height": 900,
                "hardware_weight": 2,
                "filler_area":0
            }
        ],
        "main_img": "",
        "structure_img": "",
        "linedrawing_img": "",
        "threedmax_img": "",
        "appearance_img": "",
        "official_img": "",
        "hole_site_img": "",
        "process_fee": 1,
        "author": "张三",
        "date": QDate.currentDate().toString("yyyy-MM-dd"),
        "filler_area": 25
    },
    "selected_materials": [],
    "selected_hardwares": [],
    "selected_edge_band": [],
    "selected_fits": [],
    "xml_board": {
        "xmls": {},
        "version": "2025/8/19"
    }
}
connection = http.client.HTTPConnection("yaomeng.jiajumaijia.com")
connection = http.client.HTTPSConnection("shu.yesno.vip")

def messagebox(result):
    msg = QMessageBox()
    msg.setWindowTitle(localization["mainDialog"]["windowTitle"])
    msg.setText(result)
    msg.setIcon(QMessageBox.Information)
    msg.exec()  # Popup gösterilir

def querybox(query,parent):
    msg = QMessageBox(parent)
    msg.setWindowTitle(localization["mainDialog"]["windowTitle"])
    msg.setText(query)
    msg.setIcon(QMessageBox.Question)
    msg.setStandardButtons(QMessageBox.Yes | QMessageBox.No)
    msg.setDefaultButton(QMessageBox.No)
    result = msg.exec()  # pencereyi göster ve sonucu al
    if result == QMessageBox.Yes:
        return True
    else:
        return False
accessKey = ""
class ApiWorker(QThread):
    def __init__(self, progressdialog, maindialog):
        super().__init__()
        self.maindialog = maindialog  # maindialog'u burada sakla
        self.progressdialog = progressdialog
    progress = Signal(str)  # Ana pencereye bilgi göndermek için sinyal
    def run(self):
        start_time = time.time()  # timestamp başı
        time.sleep(1)
        def upload_images(file_path):
            conn = connection
            dataList = []
            boundary = 'wL36Yn8afVp8Ag7AmP8qZ0SA4n1v9T'
            dataList.append(encode('--' + boundary))
            dataList.append(encode('Content-Disposition: form-data; name=sourceType;'))

            dataList.append(encode('Content-Type: {}'.format('text/plain')))
            dataList.append(encode(''))

            dataList.append(encode("6"))
            dataList.append(encode('--' + boundary))
            dataList.append(encode('Content-Disposition: form-data; name=path;'))

            dataList.append(encode('Content-Type: {}'.format('text/plain')))
            dataList.append(encode(''))

            dataList.append(encode(file_path))
            dataList.append(encode('--' + boundary))
            dataList.append(encode('Content-Disposition: form-data; name=thumb;'))

            dataList.append(encode('Content-Type: {}'.format('text/plain')))
            dataList.append(encode(''))

            dataList.append(encode("1"))
            dataList.append(encode('--' + boundary))
            dataList.append(encode(f'Content-Disposition: form-data; name=image; filename={os.path.basename(file_path)}'.format('')))

            fileType = mimetypes.guess_type(file_path)[0] or 'application/octet-stream'
            dataList.append(encode('Content-Type: {}'.format(fileType)))
            dataList.append(encode(''))

            with open(file_path, 'rb') as f:
                dataList.append(f.read())
            dataList.append(encode('--'+boundary+'--'))
            dataList.append(encode(''))
            body = b'\r\n'.join(dataList)
            payload = body
            headers = {
                'Authorization': 'Bearer '+self.maindialog.logintoken,
                'Content-type': 'multipart/form-data; boundary={}'.format(boundary)
            }
            conn.request("POST", "/wapi/uploadossfile", payload, headers)
            result = conn.getresponse().read()
            resultlist = (json.loads(result.decode("utf-8")))
            return resultlist
        
        # upload images
        try:
            if self.maindialog.img_local_paths.count(None) != 6:
                self.progress.emit(localization["processDialog"]["log"]["imagesUploading"]+"\n")
            for i in range(0,6):
                local_path = self.maindialog.img_local_paths[i]
                server_path = self.maindialog.img_server_paths[i]
                if server_path != None: # get defined path
                    self.progressdialog.log.append(f'{self.maindialog.img_titles[i]} {localization["processDialog"]["log"]["imagePathManuallyDefined"]}\n{server_path}\n')
                    data["main"][self.maindialog.img_mainnames[i]] = server_path
                elif local_path != None: # upload img and generate new path
                    resultlist = upload_images(local_path)
                    if resultlist["code"] == 0:
                        uploaded_path = resultlist["data"]["path"]
                        self.progressdialog.log.append(f'{self.maindialog.img_titles[i]} {localization["processDialog"]["log"]["imageUploadSuccess"]}\n{uploaded_path}\n')
                        data["main"][self.maindialog.img_mainnames[i]] = uploaded_path
                        self.maindialog.img_textboxes[i].setText(uploaded_path) # update textbox with new path
                        self.maindialog.img_server_paths[i] = uploaded_path # save new server path
                    else:
                        self.progressdialog.log.append(f'{self.maindialog.img_titles[i]} {localization["processDialog"]["log"]["imageUploadFailed"]}')
                        data["main"][self.maindialog.img_mainnames[i]] = ""
                        self.maindialog.img_textboxes[i].setText("")
                        self.maindialog.img_server_paths[i] = None
                        self.progressdialog.log.append(f'{resultlist}')
        except:self.progressdialog.log.append(localization["processDialog"]["log"]["imageUpdateError"])
        # upload product
        try:
            conn = connection
            dataList = []
            boundary = 'wL36Yn8afVp8Ag7AmP8qZ0SA4n1v9T'
            dataList.append(encode('--' + boundary))
            dataList.append(encode('Content-Disposition: form-data; name=file; filename={0}'.format('.xml')))
            fileType = mimetypes.guess_type(self.maindialog.xml_path)[0] or 'application/octet-stream'
            dataList.append(encode('Content-Type: {}'.format(fileType)))
            dataList.append(encode(''))

            with open(self.maindialog.xml_path, 'rb') as f:
                dataList.append(f.read())
            dataList.append(encode('--'+boundary+'--'))
            dataList.append(encode(''))
            body = b'\r\n'.join(dataList)
            payload = body
            headers = {
                'Authorization': 'Bearer '+self.maindialog.logintoken,
                'Content-type': 'multipart/form-data; boundary={}'.format(boundary)
            }
            conn.request("POST", "/api/jiaju/uploadxml", payload, headers)
            xmlresult = conn.getresponse().read()
            xmlresultlist = (json.loads(xmlresult.decode("utf-8")))
            #~ print(xmlresultlist)
            if xmlresultlist["code"] == 0:
                self.maindialog.data["xml_board"]["xmls"] = xmlresultlist["xmls"]
                payload = json.dumps(self.maindialog.data)
                conn = connection
                headers = {
                    'Authorization': 'Bearer '+self.maindialog.logintoken,
                    'Content-Type': 'application/json'
                }
                conn.request("POST", "/api/jiaju/product/"+self.maindialog.upload_prefix, payload, headers)
                result = conn.getresponse().read()
                resultlist = (json.loads(result.decode("utf-8")))
                #~ print(resultlist)
                # print(resultlist["code"])
                if resultlist["code"] == 0:
                    self.progressdialog.log.append(f'{resultlist["message"]}')
                    if self.maindialog.upload_prefix == "add": 
                        self.maindialog.productid_textbox.setText(str(resultlist["data"]["product_id"]))
                        self.progressdialog.log.append(f'{localization["processDialog"]["log"]["newProductid"]} {resultlist["data"]["product_id"]}\n')
                else:
                    self.progressdialog.log.append(localization["processDialog"]["log"]["productUploadError"])
                    self.progressdialog.log.append(f'{resultlist}')
            else:
                self.progressdialog.log.append(localization["processDialog"]["log"]["xmlFileUploadError"])
                self.progressdialog.log.append(f'{resultlist}')
            end_time = time.time()  # timestamp sonu
            self.progressdialog.close_btn.setEnabled(True)
            self.progressdialog.log.append(localization["processDialog"]["log"]["time"][0]+str(round((end_time-start_time), 2))+localization["processDialog"]["log"]["time"][1])
            self.progressdialog.log.append("------------------------------------------------\n")
            self.progressdialog.log.moveCursor(QTextCursor.End)
            try:
                with open(self.progressdialog.logfile, "a", encoding="utf-8") as f:
                    f.write(self.progressdialog.log.toPlainText())
            except:
                self.processdialog.log.append(localization["processDialog"]["log"]["logFileSaveError"])
        except:
            self.progressdialog.log.append(localization["processDialog"]["log"]["dataUpdateError"])
            self.progressdialog.log.append("------------------------------------------------\n")
            self.progressdialog.log.moveCursor(QTextCursor.End)
            self.progressdialog.close_btn.setEnabled(True)
            print(self.progressdialog.logfile)
            with open(self.progressdialog.logfile, "a", encoding="utf-8") as f:
                f.write(self.progressdialog.log.toPlainText())

class progressDialog(QDialog):
    def __init__(self, maindialog):
        super().__init__()
        self.maindialog = maindialog
        self.setWindowTitle(localization["mainDialog"]["windowTitle"])
        self.resize(self.maindialog.width()/3, self.maindialog.width()/3)
        self.setWindowFlags(Qt.WindowStaysOnTopHint) # her zaman ustte
        vlayout = QVBoxLayout(self)
        startmessage = QDateTime.currentDateTime().toString("yyyy-MM-dd hh:mm:ss")
        if self.maindialog.upload_prefix == "save":
            startmessage += (
                f'\n{localization["processDialog"]["log"]["productUpdate"]}\n'
                f'{localization["processDialog"]["log"]["idNumber"]}{data["product_id"]}\n'
                f'{localization["processDialog"]["log"]["jsName"]}{data["main"]["sku_js"]}\n'
            )
        else:
            startmessage += (
            f'\n{localization["processDialog"]["log"]["creatingNewProduct"]}\n'
            f'{localization["processDialog"]["log"]["jsName"]}{data["main"]["sku_js"]}\n'
            )
        startmessage += localization["processDialog"]["log"]["startUploading"]
        self.logfile = tempfile.gettempdir()+"\\JLSFProductManagement.log"
        if os.path.exists(self.logfile) == False: # log dosyayi yoksa olustur
            with open(self.logfile, "w", encoding="utf-8") as f:
                f.write("")
        if os.path.getsize(self.logfile) > 1024*1024*2: # log dosyasi 2MB'den buyukse yarısını sil
            with open(self.logfile, "r", encoding="utf-8") as f: # tum satirlari oku
                lines = f.readlines()
            with open(self.logfile, "w", encoding="utf-8") as f: # okunan satirlarin yarisini yaz
                f.writelines(lines[len(lines)//2:])
        icerik = ""
        if os.path.exists(self.logfile):
            with open(self.logfile, "r", encoding="utf-8") as f:
                icerik = f.read()
        icerik += "\n"+startmessage
        self.log = QTextEdit()
        self.log.setPlainText(icerik)
        self.log.moveCursor(QTextCursor.End)
        vlayout.addWidget(self.log)
        hlayout = QHBoxLayout()
        self.close_btn = QPushButton(localization["processDialog"]["close_btn"])
        self.close_btn.setEnabled(False)
        self.close_btn.clicked.connect(self.close)
        hlayout.addWidget(self.close_btn)
        self.clear_btn = QPushButton(localization["processDialog"]["clear_btn"])
        def clear_log_def(self):
            onay = querybox(localization["processDialog"]["clear_btn_message"],self)
            if onay:
                self.log.clear()
                with open(self.logfile, "w", encoding="utf-8") as f:
                    f.write("")
        self.clear_btn.clicked.connect(lambda: clear_log_def(self))
        hlayout.addWidget(self.clear_btn)
        vlayout.addLayout(hlayout)
        self.worker = ApiWorker(self, maindialog) # start upload api
        def update_log(message):self.log.append(message)
        self.worker.progress.connect(update_log)
        self.worker.start()
        
class mainDialog(QDialog):
    def __init__(self):
        super().__init__()
        self.setWindowTitle(localization["mainDialog"]["windowTitle"])
        self.resize(1000, 700)
        # self.setStyleSheet("QDialog{background:#f8f8f8;} QLabel{font-size:15px;} QGroupBox{font-weight:bold;}")

        # Scrollable main layout
        scroll = QScrollArea(self)
        scroll.setWidgetResizable(True)
        main_widget = QWidget()
        main_widget.resize(1200, 1200)
       
        layout = QVBoxLayout(main_widget)
        scroll.setWidget(main_widget)
        main_layout = QVBoxLayout(self)
        main_layout.addWidget(scroll)

        # Header
        header = QLabel(localization["mainDialog"]["header"]["title"])
        header.setStyleSheet("font-size: 26px; color: #409EFF; font-weight: bold; margin-bottom: 10px;")
        hbox = QHBoxLayout()
        hbox.addWidget(header, alignment=Qt.AlignLeft)
        hbox.addStretch()
        hbox2 = QHBoxLayout()
        hbox2.addStretch()
        hbox2.addWidget(QLabel(localization["mainDialog"]["header"]["login"][0]))
        self.username = QLineEdit()
        self.username.setFixedWidth(100)
        hbox2.addWidget(self.username)
        hbox2.addWidget(QLabel(localization["mainDialog"]["header"]["login"][1]))
        self.password = QLineEdit()
        self.password.setEchoMode(QLineEdit.Password)
        self.password.setFixedWidth(100)
        hbox2.addWidget(self.password)
        self.login_btn = QPushButton(localization["mainDialog"]["header"]["login"][2])
        self.tokenfile = (tempfile.gettempdir()+"\\JLSFProductManagement.data")
        self.logintoken = None
        if os.path.exists(self.tokenfile):
            with open(self.tokenfile, "r") as f:
                lines = f.read().splitlines()
            self.username.setText(lines[0])
            self.login_btn.setEnabled(False)
            self.logintoken = lines[1]

        def login_def(username, password, login):
            conn = connection
            dataList = []
            boundary = 'wL36Yn8afVp8Ag7AmP8qZ0SA4n1v9T'
            dataList.append(encode('--' + boundary))
            dataList.append(encode('Content-Disposition: form-data; name=username;'))

            dataList.append(encode('Content-Type: {}'.format('text/plain')))
            dataList.append(encode(''))
            dataList.append(encode(username)) # kullanici adi

            dataList.append(encode('--' + boundary))
            dataList.append(encode('Content-Disposition: form-data; name=password;'))

            dataList.append(encode('Content-Type: {}'.format('text/plain')))
            dataList.append(encode(''))
            dataList.append(encode(password)) # sifre

            dataList.append(encode('--'+boundary+'--'))
            dataList.append(encode(''))
            body = b'\r\n'.join(dataList)
            payload = body
            headers = {
            'Authorization': 'Bearer 69|6qTylUJS0I3tq7tgoVV4YAjbhuij0EtrABUo4GUpdaa4d7d9',
            'Content-type': 'multipart/form-data; boundary={}'.format(boundary)
            }
            conn.request("POST", "/api/login_pwd", payload, headers)
            result = conn.getresponse().read()
            resultlist = (json.loads(result.decode("utf-8")))
            if resultlist["code"] == 0:
                logintoken = resultlist["data"]["token"]
                if resultlist["code"] == 0:
                    file_path = os.path.join(tempfile.gettempdir(), os.path.basename(self.tokenfile))
                    with open(file_path, "w") as f:
                        f.write(username+"\n")
                        f.write(logintoken+"\n")
                messagebox(localization["mainDialog"]["header"]["querybox"][0])
                return logintoken
            else:
                messagebox(localization["mainDialog"]["header"]["querybox"][1])
                return None

        def handle_login(self):
            username = self.username.text()
            password = self.password.text()
            login = True # login butonuyla giris yapilirsa True, JLSFProductUpload.data dosyasi ile giris yapilirsa False
            self.logintoken = login_def(username, password, login)
            if self.logintoken != None:
                self.login_btn.setEnabled(False)
        self.login_btn.clicked.connect(lambda: handle_login(self))
        hbox2.addWidget(self.login_btn)
        self.logout_btn = QPushButton(localization["mainDialog"]["header"]["login"][3])
        def logout_def():
            if (os.path.exists(self.tokenfile)):os.remove(self.tokenfile)
            messagebox(localization["mainDialog"]["header"]["querybox"][2])
            self.login_btn.setEnabled(True)
        self.logout_btn.clicked.connect(logout_def)
        hbox2.addWidget(self.logout_btn)
        hbox.addLayout(hbox2)
        layout.addLayout(hbox)

        def data_changed(index, name1, name2, value):
            data[name1][name2] = value

        # Database Information
        form_group = QGroupBox(localization["mainDialog"]["databaseInformation"]["groupBoxTitle"])
        form_layout = QHBoxLayout()
        # labelList =  ["Made Type:","Category:", "ddnum", "psize", "SKU JS","*SKU OP:","SKU ERP:","Design Date:"]
        labelList = localization["mainDialog"]["databaseInformation"]["labelList"]
        widgetList = []
        # madetypelist = ["Original", "Update", "Replace", "Custom",] # U = UPDATE, O = ORIGINAL, C = CUSTOM MADE, P = REPLACE]
        madetypelist = localization["mainDialog"]["databaseInformation"]["madeTypeList"]
        self.madetype = QComboBox()
        self.madetype.addItems(madetypelist)
        def madetype_changed(i):
            result = None
            if i == 0:result = "O"
            elif i == 1:result = "U"
            elif i == 2:result = "R"
            elif i == 3:result = "C"
            data["main"]["madetype"] = result
        self.madetype.currentIndexChanged.connect(madetype_changed)
        widgetList.append(self.madetype)
        categorylist2 = [
            f'{item["id"]} {item["category"]} {item["serial_number"].upper()}' for item in categorylist
        ]
        self.category = QComboBox()
        self.category.addItems(categorylist2)
        
        self.category.currentIndexChanged.connect(lambda i:
            data_changed(i, "main", "category_id", categorylist[self.category.currentIndex()]["category"])
        )
        widgetList.append(self.category)
        self.ddnum = QSpinBox()
        self.ddnum.setRange(0, 99999)
        self.ddnum.setValue(1) 
        self.ddnum.valueChanged.connect(lambda i: data_changed(i, "main", "ddnum", i))
        widgetList.append(self.ddnum)
        self.psize = QSpinBox()
        self.psize.setRange(0, 99999)
        self.psize.setValue(1)
        self.psize.valueChanged.connect(lambda i: data_changed(i, "main", "psize", i))
        widgetList.append(self.psize)
        self.sku_js = QLineEdit()
        self.sku_js.textChanged.connect(lambda i: data_changed(i, "main", "sku_js", i))
        self.sku_js.setPlaceholderText("XG010901")
        widgetList.append(self.sku_js)
        self.sku_op = QLineEdit()
        self.sku_op.textChanged.connect(lambda i: data_changed(i, "main", "sku_op", i))
        self.sku_op.setPlaceholderText("PTXG010901D")
        widgetList.append(self.sku_op)
        self.sku_erp = QLineEdit()
        self.sku_erp.textChanged.connect(lambda i: data_changed(i, "main", "sku_erp", i))
        self.sku_erp.setPlaceholderText("PTXG0109")
        widgetList.append(self.sku_erp)
        self.date = QDateEdit(QDate.currentDate())
        self.date.dateChanged.connect(lambda i: data_changed(i, "main", "date", self.date.date().toString("yyyy-MM-dd")))
        self.date.setDisplayFormat("yyyy-MM-dd")
        widgetList.append(self.date)
        for i in range(len(widgetList)):
            vbox = QVBoxLayout()
            vbox.addWidget(QLabel(labelList[i]))
            vbox.addWidget(widgetList[i])
            form_layout.addLayout(vbox)
        form_group.setLayout(form_layout)
        layout.addWidget(form_group)

        # Product Parameters
        groupbox = QGroupBox(localization["mainDialog"]["productParameters"]["groupBoxTitle"])
        product_layout = QHBoxLayout()
        # labelList = ["Dimension:","Materials:","Colour:","Thickness","Author:"]
        labelList = localization["mainDialog"]["productParameters"]["labelList"]
        widgetList = []
        self.product_dimensions = QLineEdit()
        self.product_dimensions.textChanged.connect(lambda i: data_changed(i, "main", "scale", i))
        self.product_dimensions.setPlaceholderText("1200*900*300 (width*height*depth mm)")
        widgetList.append(self.product_dimensions)
        self.product_material = QLineEdit()
        self.product_material.textChanged.connect(lambda i: data_changed(i, "main", "material", i))
        self.product_material.setPlaceholderText("Fiber Board")
        widgetList.append(self.product_material)
        self.product_color = QLineEdit()
        self.product_color.textChanged.connect(lambda i: data_changed(i, "main", "color", i))
        self.product_color.setPlaceholderText("White")
        widgetList.append(self.product_color)
        self.product_thickness = QLineEdit()
        self.product_thickness.textChanged.connect(lambda i: data_changed(i, "main", "thickness", i))
        self.product_thickness.setPlaceholderText("15")
        widgetList.append(self.product_thickness)
        self.product_author = QLineEdit()
        self.product_author.textChanged.connect(lambda i: data_changed(i, "main", "author", i))
        self.product_author.setPlaceholderText(labelList[4])
        widgetList.append(self.product_author)
        for label, widget in list(zip(labelList,widgetList)):
            vbox = QVBoxLayout()
            vbox.addWidget(QLabel(label))
            vbox.addWidget(widget)
            product_layout.addLayout(vbox)
        groupbox.setLayout(product_layout)
        layout.addWidget(groupbox)

        # Image Uploads
        img_group = QGroupBox(localization["mainDialog"]["imageUploads"]["groupBoxTitle"])
        img_layout = QHBoxLayout()
        self.img_labels = []
        self.img_textboxes = []
        # self.img_titles = ["Main", "Appearance", "Structure", "Line Drawing", "Official", "Hole Site"]
        self.img_titles = localization["mainDialog"]["imageUploads"]["imgTitles"]
        self.img_mainnames = ["main_img","structure_img","linedrawing_img","appearance_img","official_img","hole_site_img"]
        self.img_local_paths = len(self.img_titles) * [None]
        self.img_server_paths = len(self.img_titles) * [None]
        def select_image(self, idx):
            if self.img_local_paths[idx] == None:
                path, _ = QFileDialog.getOpenFileName(self, "Select Image", "", "Images (*.png *.jpg *.jpeg *.bmp)")
                self.img_local_paths[idx] = path
                self.img_textboxes[idx].setText(path)
                data["main"][self.img_mainnames[idx]] = path
                pix = QPixmap(path).scaled(self.img_labels[idx].width(), self.img_labels[idx].height(), Qt.KeepAspectRatio)
                self.img_labels[idx].setAlignment(Qt.AlignCenter)
                # self.img_labels[idx].setScaledContents(True) # resmi alana tam sigdirmak icin
                self.img_labels[idx].setPixmap(pix)
            else:
                self.img_local_paths[idx] = None
                self.img_labels[idx].clear()
                self.img_textboxes[idx].clear()
                self.img_server_paths[idx] = None
        for j, title in enumerate(self.img_titles):
            vbox = QVBoxLayout()
            label = QLabel()
            label.setFixedHeight(120)
            label.setStyleSheet("border:1px solid #ccc; background:#fafafa;")
            vbox.addWidget(label)
            btn = QPushButton(title)
            btn.clicked.connect(lambda idx=j: select_image(self, idx))
            vbox.addWidget(btn)
            path_textbox = QLineEdit()
            path_textbox.textChanged.connect(lambda i, name2=self.img_mainnames[j]: data_changed(i, "main", name2, i))
            self.img_textboxes.append(path_textbox)
            clear_path_textbox = QPushButton("x")
            clear_path_textbox.setFixedWidth(30)
            def clear_path_def(idx):
                self.img_textboxes[idx].clear()
                self.img_server_paths[idx] = None
            clear_path_textbox.clicked.connect(lambda idx=j: clear_path_def(idx))
            hbox = QHBoxLayout()
            hbox.addWidget(path_textbox)
            # hbox.addWidget(clear_path_textbox)
            vbox.addLayout(hbox)
            img_layout.addLayout(vbox)
            self.img_labels.append(label)
        img_group.setLayout(img_layout)
        layout.addWidget(img_group)

        # Package Parameters
        groupbox = QGroupBox(localization["mainDialog"]["packageParameters"]["groupBoxTitle"])
        package_layout = QVBoxLayout()
        self.addnewpackage_btn = QPushButton("+")
        self.addnewpackage_btn.setFixedWidth(80)
        self.removepackage_btn = QPushButton("-")
        self.removepackage_btn.setFixedWidth(80)
        eklecikar_layout = QHBoxLayout()
        eklecikar_layout.addWidget(self.addnewpackage_btn)
        eklecikar_layout.addWidget(self.removepackage_btn)
        eklecikar_layout.addStretch()
        self.package_rows = [] # --- Paket satırlarını saklamak için
        def addnewpackage_def():
            data["main"]["pkgs"].append(
                {
                "pkg_length": 0,
                "pkg_width": 0,
                "pkg_height": 0,
                "hardware_weight": 0,
                "filler_area":0
                }
            )
            def package_textchanged(value, name, i):
                data["main"]["pkgs"][i][name] = value
            hbox = QHBoxLayout()
            pkg_width = QLineEdit()
            pkg_width.setPlaceholderText("mm")
            pkg_width.textChanged.connect(lambda value, name="pkg_width", i=(len(self.package_rows)): package_textchanged(value, name, i))
            pkg_length = QLineEdit()
            pkg_length.setPlaceholderText("mm")
            pkg_length.textChanged.connect(lambda value, name="pkg_length", i=(len(self.package_rows)): package_textchanged(value, name, i))
            pkg_height = QLineEdit()
            pkg_height.setPlaceholderText("mm")
            pkg_height.textChanged.connect(lambda value, name="pkg_height", i=(len(self.package_rows)): package_textchanged(value, name, i))
            pkg_weight = QLineEdit()
            pkg_weight.setPlaceholderText("kg")
            pkg_weight.textChanged.connect(lambda value, name="hardware_weight", i=(len(self.package_rows)): package_textchanged(value, name, i))
            pkg_filler = QLineEdit()
            pkg_filler.setPlaceholderText("count")
            pkg_filler.textChanged.connect(lambda value, name="filler_area", i=(len(self.package_rows)): package_textchanged(value, name, i))
            hbox.addWidget(pkg_width)
            hbox.addWidget(pkg_length)
            hbox.addWidget(pkg_height)
            hbox.addWidget(pkg_weight)
            hbox.addWidget(pkg_filler)
            self.package_rows.append(hbox)
            package_layout.addLayout(hbox)
        def remove_package_def():
            if len(self.package_rows) > 2:
                last_row = self.package_rows.pop()   # son ekleneni al
                package_layout.removeItem(last_row)
                last_row.deleteLater()
                del data["main"]["pkgs"][len(self.package_rows)]
        package_layout.addLayout(eklecikar_layout)
        data["main"]["pkgs"].clear()
        hbox = QHBoxLayout()
        # labellist = ["Width:","Length:","Height:","Weight:","Filler Area:"]
        labellist = localization["mainDialog"]["packageParameters"]["labelList"]
        for label in labellist:
            hbox.addWidget(QLabel(label))
        package_layout.addLayout(hbox)
        addnewpackage_def() # 1. paket (zorunlu)
        addnewpackage_def() # 2. paket (zorunlu)
        groupbox.setLayout(package_layout)
        self.addnewpackage_btn.clicked.connect(lambda: addnewpackage_def())
        self.removepackage_btn.clicked.connect(remove_package_def)
        layout.addWidget(groupbox)

        # Additional Accessories
        groupbox = QGroupBox("Additional Accessories")
        accessory_layout = QVBoxLayout()
        self.addnewaccessory_btn = QPushButton("+")
        self.addnewaccessory_btn.setFixedWidth(80)
        self.removeaccessory_btn = QPushButton("-")
        self.removeaccessory_btn.setFixedWidth(80)
        eklecikar_layout = QHBoxLayout()
        eklecikar_layout.addWidget(self.addnewaccessory_btn)
        eklecikar_layout.addWidget(self.removeaccessory_btn)
        eklecikar_layout.addStretch()
        self.accessory_rows = [] # --- Paket satırlarını saklamak için
        def add_new_accessory_def():
            data["selected_fits"].append({
                "name": "0",
                "scale": "0*0",
                "number": 1, # adet
                "price": 0,
                "comments": "0"
            })
            def accessory_textchanged(text, name, i):
                data["selected_fits"][i][name] = text
            hbox = QHBoxLayout()
            pkg_width = QLineEdit()
            pkg_width.setPlaceholderText("")
            pkg_width.textChanged.connect(lambda text, name="name", i=(len(self.accessory_rows)): accessory_textchanged(text, name, i))
            pkg_length = QLineEdit()
            pkg_length.setPlaceholderText("")
            pkg_length.textChanged.connect(lambda text, name="scale", i=(len(self.accessory_rows)): accessory_textchanged(text, name, i))
            pkg_height = QLineEdit()
            pkg_height.setPlaceholderText("")
            pkg_height.textChanged.connect(lambda text, name="number", i=(len(self.accessory_rows)): accessory_textchanged(text, name, i))
            pkg_weight = QLineEdit()
            pkg_weight.setPlaceholderText("")
            pkg_weight.textChanged.connect(lambda text, name="price", i=(len(self.accessory_rows)): accessory_textchanged(text, name, i))
            pkg_filler = QLineEdit()
            pkg_filler.setPlaceholderText("")
            pkg_filler.textChanged.connect(lambda text, name="comments", i=(len(self.accessory_rows)): accessory_textchanged(text, name, i))
            hbox.addWidget(pkg_width)
            hbox.addWidget(pkg_length)
            hbox.addWidget(pkg_height)
            hbox.addWidget(pkg_weight)
            hbox.addWidget(pkg_filler)
            self.accessory_rows.append(hbox)
            accessory_layout.addLayout(hbox)
        def remove_accessory_def():
            if len(self.accessory_rows) != 0:
                last_row = self.accessory_rows.pop()   # son ekleneni al
                accessory_layout.removeItem(last_row)
                last_row.deleteLater()
                del data["selected_fits"][len(self.accessory_rows)]
        accessory_layout.addLayout(eklecikar_layout)
        data["selected_fits"].clear()
        hbox = QHBoxLayout()
        labellist = ["Name","Scale","Quantity","Price","Comments"]
        for label in labellist:
            hbox.addWidget(QLabel(label))
        accessory_layout.addLayout(hbox)
        groupbox.setLayout(accessory_layout)
        self.addnewaccessory_btn.clicked.connect(lambda: add_new_accessory_def())
        self.removeaccessory_btn.clicked.connect(remove_accessory_def)
        layout.addWidget(groupbox)

        # === excel ===
        main_group = QGroupBox(localization["mainDialog"]["excelFile"]["groupBoxTitle"])
        main_group.setMinimumHeight(300)
        excel_layout = QVBoxLayout()
        btn_layout = QHBoxLayout()
        table_layout = QHBoxLayout()
        excel_layout.addLayout(btn_layout)
        excel_layout.addLayout(table_layout)
        main_group.setLayout(excel_layout)
        self.tabs = QTabWidget()
        self.tabs.setTabPosition(QTabWidget.South)  # Sekmeleri alta koyar
        def change_cell(row, col, table): # hucre de degisiklik yapilirsa
            new_value = table.item(row, col).text()
            if self.tabs.currentIndex() == 0:
                cell = data["selected_materials"][row]
                keys = list(data["selected_materials"][row].keys()) #isimler ["material","material_no",...]
                if col == 1:
                    cell[keys[0]] = new_value # material
                elif col == 2:
                    cell[keys[1]] = new_value # material_no
                elif col == 3:
                    cell[keys[2]] = new_value # name
                elif col == 4:
                    cell[keys[3]] = new_value # color
                elif col == 5:
                    try:cell[keys[4]] = float(new_value) # length
                    except:cell[keys[4]] = 0
                elif col == 6:
                    try:cell[keys[5]] = float(new_value) # width
                    except:cell[keys[5]] = 0
                elif col == 7:
                    try:cell[keys[6]] = float(new_value) # thickness
                    except:cell[keys[6]] = 0
                elif col == 8:
                    try:cell[keys[7]] = int(float(new_value)) # quantity
                    except:cell[keys[7]] = 0
                elif col == 11:
                    try:cell[keys[8]] = int(float(new_value)) # front
                    except: cell[keys[8]] = 0
                elif col == 12:
                    try:cell[keys[9]] = int(float(new_value)) # after
                    except: cell[keys[9]] = 0
                elif col == 13:
                    try:cell[keys[10]] = int(float(new_value)) # left
                    except:cell[keys[10]] = 0
                elif col == 14:
                    try:cell[keys[11]] = int(float(new_value)) # right
                    except:cell[keys[11]] = 0
                elif col == 15:
                    try:cell[keys[12]] = int(float(new_value)) # panel_visible
                    except:cell[keys[12]] = 0

        def load_excel_def(excel_path):
            if excel_path:
                self.tabs.clear()
                all_sheets = pd.read_excel(excel_path, sheet_name=None) # ilk satirin baslik olmamasi icin > header=None  
                def fill_table_from_df(table, dataframe, i):
                    table.setRowCount(len(dataframe))
                    table.setColumnCount(len(dataframe.columns))
                    table.setHorizontalHeaderLabels(dataframe.columns)
                    if i == 0:data["selected_materials"].clear() # her seferinde temizle
                    elif i == 1:
                        data["selected_hardwares"].clear()
                        data["selected_edge_band"].clear()
                        data["selected_fits"] = [{
                                "name": "None",
                                "scale": "0*0",
                                "number": 0,
                                "price": 0,
                                "comments": "None"  
                        }]
                    for row in range(len(dataframe)):
                        new_panel = {
                            "material": "马六甲板",
                            "material_no": "1",
                            "name": "右侧板",
                            "color": "暖白",
                            "length": 950,
                            "width": 360,
                            "thickness": 15,
                            "number": 1,
                            "front": 1,
                            "after": 1,
                            "left": 1,
                            "right": 1,
                            "panel_visible": 1,
                            "holes": [],
                            "signs": [],
                            "eb_color": "",
                            "pkg_floor": 0
                        }
                        new_hardware = {
                            "name": "三合一",
                            "code": "W2",
                            "comments": "",
                            "number": 46
                        }
                        new_edgeband = {
                            "color": "田园橡木",
                            "width": 16,
                            "thickness": 1,
                            "meters": 2
                        }
                        for col in range(len(dataframe.columns)):
                            value = str(dataframe.iat[row, col])
                            if value == "nan": value = ""
                            if i == 0 :
                                keys = list(new_panel.keys()) #isimler ["material","material_no",...]
                                if row >= 0: # pandas, exceldeki ilk satiri baslik olarak alıyor. bu yuzden okumaya 2. satirdan basliyor.
                                    #ilk satiri okumak icin pd.read_excel(filename,header=None) komutunu kullan
                                    if col == 1:
                                        new_panel[keys[0]] = value # material
                                    elif col == 2:
                                        new_panel[keys[1]] = value # material_no
                                    elif col == 3:
                                        new_panel[keys[2]] = value # name
                                    elif col == 4:
                                        new_panel[keys[3]] = value # color
                                    elif col == 5:
                                        try:new_panel[keys[4]] = float(value) # length
                                        except:new_panel[keys[4]] = 0
                                    elif col == 6:
                                        try:new_panel[keys[5]] = float(value) # width
                                        except:new_panel[keys[5]] = 0
                                    elif col == 7:
                                        try:new_panel[keys[6]] = float(value) # thickness
                                        except:new_panel[keys[6]] = 0
                                    elif col == 8:
                                        try:new_panel[keys[7]] = int(float(value)) # quantity
                                        except:new_panel[keys[7]] = 0
                                    elif col == 11:
                                        try:new_panel[keys[8]] = int(float(value)) # front
                                        except:new_panel[keys[8]] = 0
                                    elif col == 12:
                                        try:new_panel[keys[9]] = int(float(value)) # after
                                        except:new_panel[keys[9]] = 0   
                                    elif col == 13:
                                        try:new_panel[keys[10]] = int(float(value)) # left
                                        except:new_panel[keys[10]] = 0
                                    elif col == 14:
                                        try:new_panel[keys[11]] = int(float(value)) # right
                                        except:new_panel[keys[11]] = 0
                                    elif col == 15:
                                        try:new_panel[keys[12]] = int(float(value)) # panel_visible
                                        except:new_panel[keys[12]] = 0
                            elif i == 1:
                                code = (str(dataframe.iat[row, 2]))
                                if code == "nan": code = "0"
                                if code[0] == "W":
                                    if col == 2:
                                        new_hardware["code"] = value
                                    elif col == 3:
                                        new_hardware["name"] = value
                                    elif col == 4:
                                        new_hardware["number"] = value
                            table.setItem(row, col, QTableWidgetItem(value)) # hucreye isle
                        if i == 0:
                            data["selected_materials"].append(new_panel) # json'a isle
                        elif i == 1:
                            code = (str(dataframe.iat[row, 2]))
                            if code == "nan": code = "0"
                            if code[0] == "W":data["selected_hardwares"].append(new_hardware)
                            elif code[0] == "F":data["selected_edge_band"].append(new_edgeband)
                for i in range(len(all_sheets.items())):
                    sheet_name, df = list(all_sheets.items())[i]
                    table = QTableWidget()
                    fill_table_from_df(table, df, i) # DataFrame'den tabloyu doldur
                    table.cellChanged.connect(
                        lambda r, c, t=table: change_cell(r,c,t)
                    )
                    self.tabs.addTab(table, sheet_name)
        def clear_btn_def(self):
            self.tabs.clear()
            self.table_panel.setHorizontalHeaderLabels([
                "File Name", "Class Name", "Panel Id", "Object Name", "Material Name",
                "Size of Long", "Size of Short", "Thickness", "Quantity", "Pattern Direction",
                "Edgeband Info", "Edgeband Front", "Edgeband Back", "Edgeband Left",
                "Edgeband Right", "Edgeband Thickness", "Edgeband Color", "Edgeband Length"
            ])
            self.tabs.addTab(self.table_panel, "Panel List")
            self.table_hardware.setHorizontalHeaderLabels([
                "File Name", "Object Code", "Material Code", "Material Name",
                "Amount", "Unit", "Price", "Total Cost"
            ])
            self.tabs.addTab(self.table_hardware, "Hardware List")
            table_layout.addWidget(self.tabs)
        btn_layout.addStretch()
        loadexcel_btn = QPushButton(localization["mainDialog"]["excelFile"]["loadexcel_btn"])
        def select_excel_file(self):
            self.excel_path, _ = QFileDialog.getOpenFileName(self,"Select Excel File","","Excel File (*.xlsx)") #self, Pencere basligi, Başlangic dizini, Filtreler
            # self.excel_path = "C:/users/admin/desktop/cnc//test.xlsx"
            load_excel_def(self.excel_path)
        loadexcel_btn.clicked.connect(lambda: select_excel_file(self))
        loadexcel_btn.setFixedWidth(150)
        self.table_panel = QTableWidget(10, 18)
        self.table_hardware = QTableWidget(10, 6)
        clear_btn_def(self)
        btn_layout.addWidget(loadexcel_btn, alignment=Qt.AlignRight)
        clear_btn = QPushButton(localization["mainDialog"]["excelFile"]["clear_btn"])
        clear_btn.setFixedWidth(150)
        clear_btn.clicked.connect(lambda: clear_btn_def(self))
        btn_layout.addWidget(clear_btn, alignment=Qt.AlignRight)
        clear_btn.clicked.connect(lambda: (self.table_panel.clearContents(), self.table_hardware.clearContents()))
        layout.addWidget(main_group)

        # --- xml ----
        main_groupxml = QGroupBox(localization["mainDialog"]["xmlFile"]["groupBoxTitle"])
        main_groupxml.setMinimumHeight(300)
        xml_layout = QVBoxLayout()
        btn_layoutxml = QHBoxLayout()
        table_layoutxml = QHBoxLayout()
        xml_layout.addLayout(btn_layoutxml)
        xml_layout.addLayout(table_layoutxml)
        main_groupxml.setLayout(xml_layout)
        self.tabsxml = QTabWidget()
        self.tabsxml.setTabPosition(QTabWidget.South)  # Sekmeleri alta koyar

        def load_xml_def(xml_path):
            if xml_path:
                data["xml_board"]["xmls"].clear()
                tree = et.parse(xml_path)
                root = tree.getroot()
                item = (root.findall("Plates")[0].findall("Plate"))
                satirsayisi = len(item)
                sutunsayisi = len(item[0].items())
                self.table_panelxml.setColumnCount(sutunsayisi)
                self.table_panelxml.setRowCount(satirsayisi)
                for plates in root.findall("Plates"):
                    sorted_plates = sorted(plates, key=lambda x: int(x.get("plateNumber")))
                    for row, plate in enumerate(sorted_plates):
                        for column, attributes in enumerate(plate.items()):
                            attr = (plate.get(attributes[0]))
                            self.table_panelxml.setItem(row, column, QTableWidgetItem(str(attr)))
        def clear_btn_def2():
            self.tabsxml.clear()
            self.table_panelxml.setHorizontalHeaderLabels([
                "Plate Number","iOrder", "CabinetName", "plateNickName", "width", "depth","height","plateFlat",
                "materialName","materialColor","textureName","mapsType","created_at",
                "Sarfinet","positionAbs","positionRel","rotation"
            ])
            self.tabsxml.addTab(self.table_panelxml, "Plate List")
            table_layoutxml.addWidget(self.tabsxml)
        btn_layoutxml.addStretch()
        loadxml_btn = QPushButton(localization["mainDialog"]["xmlFile"]["loadxml_btn"])
        #~ self.xml_path = "C:/users/admin/desktop/cnc/test.xml"
        def select_xml_file(self):
            self.xml_path, _ = QFileDialog.getOpenFileName(self,"Select Xml File","","Xml File (*.xml)") #self,Pencere başlığı,Başlangıç dizini,Filtreler  
            load_xml_def(self.xml_path)
        loadxml_btn.clicked.connect(lambda: select_xml_file(self))
        loadxml_btn.setFixedWidth(150)
        self.table_panelxml = QTableWidget(10, 17)
        self.table_panelxml.setEditTriggers(QTableWidget.NoEditTriggers)
        clear_btn_def2()
        btn_layoutxml.addWidget(loadxml_btn, alignment=Qt.AlignRight)
        clear_btn = QPushButton(localization["mainDialog"]["xmlFile"]["clear_btn"])
        clear_btn.setFixedWidth(150)
        clear_btn.clicked.connect(lambda: clear_btn_def2())
        btn_layoutxml.addWidget(clear_btn, alignment=Qt.AlignRight)
        clear_btn.clicked.connect(lambda: (self.table_panelxml.clearContents()))
        layout.addWidget(main_groupxml)

        # Save buttons
        save_layout = QHBoxLayout()
        self.productid_textbox = QLineEdit("1")
        def productid_textbox_changed(i):data["main"]["productid_textbox"] = i
        self.productid_textbox.textChanged.connect(productid_textbox_changed)
        self.productid_textbox.setFixedWidth(100)
        self.productid_textbox.setPlaceholderText("1")
        self.update_btn = QPushButton(localization["mainDialog"]["bottomSection"]["update_btn"])
        def update_btn_pressed():
            onay = querybox(
                (f'{localization["mainDialog"]["bottomSection"]["update_btn_querybox"][0]}{self.productid_textbox.text()}'
                f'\n\n'
                f'{localization["mainDialog"]["bottomSection"]["update_btn_querybox"][1]}'),
                self
            )
            if onay:
                self.data = dict(data)
                self.upload_prefix = "save"
                self.start_upload()
        self.update_btn.pressed.connect(update_btn_pressed)
        productid_label = QLabel("Product ID:")
        productid_label.setFixedWidth(100)
        save_layout.addWidget(productid_label)
        save_layout.addWidget(self.productid_textbox)
        save_layout.addWidget(self.update_btn)
        self.createnew_btn = QPushButton(localization["mainDialog"]["bottomSection"]["create_btn"])
        def createnew_btn_pressed():
            onay = querybox(localization["mainDialog"]["bottomSection"]["create_btn_querybox"],self)
            if onay:
                self.data = dict(data)
                del self.data["product_id"]
                self.upload_prefix = "add"
                self.start_upload()
        self.createnew_btn.pressed.connect(createnew_btn_pressed)
        save_layout.addWidget(self.createnew_btn)
        layout.addLayout(save_layout)
        self.setLayout(main_layout)
    def start_upload(self):
        self.progressdialog = progressDialog(self)
        self.progressdialog.show()

if __name__ == "__main__":
    # app =  QApplication([]) # start aplication with windows terminal
    app = QApplication.instance() # start application with 3ds max terminal
    mw = QMainWindow()
    mw.setWindowTitle(localization["mainDialog"]["windowTitle"])
    central = mainDialog()
    mw.setCentralWidget(central)
    screen = QApplication.primaryScreen()
    mw.resize(((screen.size()).width())/1.5, screen.size().height()/1.2)
    mw.show()
    # app.exec() # start aplication with windows terminal
