class TalimatciPencere(QMainWindow): def __init__(self, ebeveyn=None): super(TalimatciPencere, self).__init__(ebeveyn) merkez_widget = QWidget() self.setCentralWidget(merkez_widget) merkez_kutu = QVBoxLayout() merkez_widget.setLayout(merkez_kutu) ####################################### # Gerek değişkenleri # ####################################### self.secilen_gerekler_liste = [] self.var_olan_gerekler_liste = [] self.yuzen_pencere = QDockWidget("Talimat Dizini", self) self.yuzen_pencere.setAllowedAreas(Qt.RightDockWidgetArea | Qt.LeftDockWidgetArea) self.yuzen_pencere.setMinimumWidth(150) self.dizin_listesi = QListWidget() self.dizin_listesi.setContextMenuPolicy(Qt.ActionsContextMenu) dosya_olustur_aksiyon = QAction("Dosya Oluştur", self, triggered=self.dosya_olustur) self.dizin_listesi.addAction(dosya_olustur_aksiyon) dosya_adi_degis_aksiyon = QAction("Dosya Adı Değiştir", self, triggered=self.dosya_adi_degis) self.dizin_listesi.addAction(dosya_adi_degis_aksiyon) self.dizin_listesi.itemDoubleClicked.connect(self.talimat_dizin_ac) yuzen_widget = QWidget() self.yuzen_pencere.setWidget(yuzen_widget) yuzen_kutu = QVBoxLayout() yuzen_widget.setLayout(yuzen_kutu) yuzen_kutu.addWidget(self.dizin_listesi) self.addDockWidget(Qt.LeftDockWidgetArea, self.yuzen_pencere) self.farkli_kaydet_dugme = QPushButton("Farklı Kaydet") self.farkli_kaydet_dugme.clicked.connect(self.farkli_yaz) yuzen_kutu.addWidget(self.farkli_kaydet_dugme) self.kaydet_dugme = QPushButton("Kaydet") self.kaydet_dugme.clicked.connect(self.yaz) yuzen_kutu.addWidget(self.kaydet_dugme) self.talimat_indir_dugme = QPushButton("Talimat İndir") self.talimat_indir_dugme.clicked.connect(self.talimat_indir_fonk) yuzen_kutu.addWidget(self.talimat_indir_dugme) self.derle_dugme = QPushButton("Derle") self.derle_dugme.clicked.connect(self.derle_fonk) yuzen_kutu.addWidget(self.derle_dugme) self.url_kontrol_dugme = QPushButton("Url Kontrol") self.url_kontrol_dugme.clicked.connect(self.url_kontrol_fonk) yuzen_kutu.addWidget(self.url_kontrol_dugme) self.gerek_kontrol_dugme = QPushButton("Gerek Kontrol") self.gerek_kontrol_dugme.clicked.connect(self.gerek_kontrol_fonk) yuzen_kutu.addWidget(self.gerek_kontrol_dugme) ac_kutu = QHBoxLayout() merkez_kutu.addLayout(ac_kutu) self.ac_dugme = QPushButton("Aç") self.ac_dugme.clicked.connect(self.ac_func) ac_kutu.addWidget(self.ac_dugme) self.acilan_url = QLineEdit() self.acilan_url.setReadOnly(True) ac_kutu.addWidget(self.acilan_url) ac_kutu = QHBoxLayout() merkez_kutu.addLayout(ac_kutu) self.talimatname_dugme = QPushButton("Talimatname") self.talimatname_dugme.clicked.connect(self.talimatname_ac_func) ac_kutu.addWidget(self.talimatname_dugme) self.talimatname = QLineEdit() self.talimatname.setReadOnly(True) ac_kutu.addWidget(self.talimatname) form_kutu = QHBoxLayout() merkez_kutu.addLayout(form_kutu) self.program_ad = QLineEdit() form_ad_label = QLabel("Ad") form_ad_label.setFixedWidth(45) form_kutu.addWidget(form_ad_label) form_kutu.addWidget(self.program_ad) self.program_surum = QLineEdit() form_surum = QLabel("Sürüm") form_surum.setFixedWidth(40) form_kutu.addWidget(form_surum) form_kutu.addWidget(self.program_surum) self.program_devir = QLineEdit() form_devir = QLabel("Devir") form_devir.setFixedWidth(40) form_kutu.addWidget(form_devir) form_kutu.addWidget(self.program_devir) form_kutu = QHBoxLayout() merkez_kutu.addLayout(form_kutu) self.program_url = QLineEdit() form_url = QLabel("Url") form_url.setFixedWidth(45) form_kutu.addWidget(form_url) form_kutu.addWidget(self.program_url) form_paketci = QLabel("Paketçi") form_paketci.setFixedWidth(45) form_kutu.addWidget(form_paketci) self.program_paketci = QLineEdit() form_kutu.addWidget(self.program_paketci) form_kutu = QHBoxLayout() merkez_kutu.addLayout(form_kutu) self.program_tanim = QLineEdit() form_tanim = QLabel("Tanım") form_tanim.setFixedWidth(45) form_kutu.addWidget(form_tanim) form_kutu.addWidget(self.program_tanim) form_kutu = QHBoxLayout() merkez_kutu.addLayout(form_kutu) self.program_kaynak = QTextEdit() self.program_kaynak.setFixedHeight(80) form_source = QLabel("Kaynak") form_source.setFixedWidth(45) form_kutu.addWidget(form_source) form_kutu.addWidget(self.program_kaynak) grub_kutu = QHBoxLayout() merkez_kutu.addLayout(grub_kutu) grub_label = QLabel("Grup") grub_label.setFixedWidth(40) grub_kutu.addWidget(grub_label) self.gruplar_combo = QComboBox() self.varolan_grup_list = self.gruplar_al() self.varolan_grup_list.sort() self.secilen_grub_liste = [] self.gruplar_combo.addItems(self.varolan_grup_list) grub_kutu.addWidget(self.gruplar_combo) self.saga_grup_dugme = QPushButton(">") self.saga_grup_dugme.setFixedWidth(40) self.saga_grup_dugme.clicked.connect(self.saga_grup_fonk) grub_kutu.addWidget(self.saga_grup_dugme) self.sola_grup_dugme = QPushButton("<") self.sola_grup_dugme.setFixedWidth(40) self.sola_grup_dugme.clicked.connect(self.sola_grup_fonk) grub_kutu.addWidget(self.sola_grup_dugme) self.program_grup = QComboBox() grub_kutu.addWidget(self.program_grup) self.grup_ekle = QPushButton("+") self.grup_ekle.setFixedWidth(40) self.grup_ekle.clicked.connect(self.grup_ekle_fonk) grub_kutu.addWidget(self.grup_ekle) merkez_kutu.addWidget(QLabel("Talimatlar")) gerek_kutu = QHBoxLayout() merkez_kutu.addLayout(gerek_kutu) self.var_olan_gerekler = QListWidget() self.var_olan_gerekler.setMaximumHeight(100) self.var_olan_gerekler.itemDoubleClicked.connect(self.talimat_ac) gerek_kutu.addWidget(self.var_olan_gerekler) dugme_kutu = QVBoxLayout() gerek_kutu.addLayout(dugme_kutu) self.saga_dugme = QPushButton("Gerek Ekle") self.saga_dugme.clicked.connect(self.saga_dugme_fonk) dugme_kutu.addWidget(self.saga_dugme) self.sola_dugme = QPushButton("Gerek sil") self.sola_dugme.clicked.connect(self.sola_dugme_fonk) dugme_kutu.addWidget(self.sola_dugme) sag_dugme_kutu = QVBoxLayout() gerek_kutu.addLayout(sag_dugme_kutu) self.secilen_gerekler = QListWidget() self.secilen_gerekler.setMaximumHeight(80) sag_dugme_kutu.addWidget(self.secilen_gerekler) self.gerek_ekle_dugme = QPushButton("Yeni Gerek Ekle") self.gerek_ekle_dugme.clicked.connect(self.gerek_ekle) sag_dugme_kutu.addWidget(self.gerek_ekle_dugme) merkez_kutu.addWidget(QLabel("Derle")) self.program_build = QTextEdit() self.program_build.setMaximumHeight(100) merkez_kutu.addWidget(self.program_build) merkez_kutu.addWidget(QLabel("Konsol")) self.terminal = QTextEdit() self.terminal.setReadOnly(True) merkez_kutu.addWidget(self.terminal) def gruplar_al(self): fname = "gruplar" with open(fname) as f: icerik = f.readlines() icerik = [x.strip() for x in icerik] return icerik def talimat_indir_fonk(self): self.talimat_indir_pencere = TalimatindirSinif(self) self.talimat_indir_pencere.show() def gerek_kontrol_fonk(self): pass def url_kontrol_fonk(self): pass def derleme_bitti_fonk(self): self.derle_dugme.setDisabled(False) self.terminal.verticalScrollBar().setValue( self.terminal.verticalScrollBar().maximum()) def derle_fonk(self): if self.acilan_url.text() != "": self.derle_dugme.setDisabled(True) self.terminal.clear() self.komut = "mps -zd " + self.program_ad.text() terminal_thread = TerminalThread(self) terminal_thread.update.connect(self.update) terminal_thread.finished.connect(self.derleme_bitti_fonk) terminal_thread.start() def update(self, cikti): self.terminal.setText(self.terminal.toPlainText() + "\n" + cikti) def talimat_ac(self): secilen = self.var_olan_gerekler.currentItem().text() url = self.talimatname.text( ) + os.sep + secilen[0] + os.sep + secilen + os.sep + "talimat" self.acilan_url.setText(url) self.oku(url) def grup_ekle_fonk(self): grup_ekle_pencere = GrupEkle(self) grup_ekle_pencere.show() def sola_grup_fonk(self): secilen = self.program_grup.currentText() if secilen != "": self.secilen_grub_liste.remove(secilen) self.program_grup.clear() self.program_grup.addItems(self.secilen_grub_liste) def saga_grup_fonk(self): secilen = self.gruplar_combo.currentText() if secilen != "": if secilen not in self.secilen_grub_liste: self.secilen_grub_liste.append(secilen) self.program_grup.clear() self.program_grup.addItems(self.secilen_grub_liste[::-1]) def saga_dugme_fonk(self): secilen = self.var_olan_gerekler.currentItem() if secilen != None: secilen = secilen.text() self.gerek_ekle_fonk(secilen) def sola_dugme_fonk(self): secilen = self.secilen_gerekler.currentItem() if secilen != None: secilen = secilen.text() self.secilen_gerekler_liste.remove(secilen) self.secilen_gerekler.clear() self.secilen_gerekler.addItems(self.secilen_gerekler_liste) def gerek_ekle(self): gerek_pencere = GerekEkle(self) gerek_pencere.show() def ac_func(self): dosya = QFileDialog.getOpenFileName(self, self.tr("Talimat Dosyası Aç"), "", "") if dosya: if dosya != ("", ""): if os.path.split(dosya[0])[1] == "talimat": self.acilan_url.setText(dosya[0]) self.oku(dosya[0]) else: QMessageBox.warning(self, "Hata", "Lütfen Bir Talimat Dosyası Seçiniz") def talimatname_ac_func(self): dizin = QFileDialog.getExistingDirectory(self, self.tr("Talimatname Dizini"), "/root/talimatname/genel", QFileDialog.ShowDirsOnly) if dizin: if dizin != ("", ""): self.talimatname.setText(dizin) self.gerek_doldur_fonk(dizin) else: QMessageBox.warning(self, "Hata", "Lütfen Bir Gerec Urlsi Seçiniz") def yaz(self): if os.path.exists(self.acilan_url.text()): f = open(self.acilan_url.text(), "w") f.write(self.yazilacak_hazirla()) f.close() QMessageBox.information(self, "Kaydedildi", "Kayıt işlemi başarıyla gerçekleştirildi") def farkli_yaz(self): kaydet = QFileDialog.getSaveFileUrl(self, self.tr("Talimat Dosyası Kaydet"), "", "") if kaydet: if kaydet != (QUrl(''), ''): url = kaydet[0].toString()[7:] f = open(url, "w") f.write(self.yazilacak_hazirla()) f.close() QMessageBox.information( self, "Kaydedildi", "Kayıt işlemi başarıyla gerçekleştirildi") def yazilacak_hazirla(self): yazilacak = "" yazilacak += "# Tanım:" + self.program_tanim.text() + "\n" yazilacak += "# URL: " + self.program_url.text() + "\n" yazilacak += "# Paketçi: " + self.program_paketci.text() + "\n" yazilacak += "# Gerekler: " + " ".join( self.secilen_gerekler_liste) + "\n" yazilacak += "# Grup: " + " ".join(self.secilen_grub_liste) + "\n\n" yazilacak += "isim=" + self.program_ad.text() + "\n" yazilacak += "surum=" + self.program_surum.text() + "\n" yazilacak += "devir=" + self.program_devir.text() + "\n" yazilacak += "kaynak=(" + self.program_kaynak.toPlainText().replace( "\n", "\n ") + ")\n\n" yazilacak += self.program_build.toPlainText() return yazilacak def temizle(self): self.secilen_gerekler.clear() self.program_grup.clear() self.secilen_gerekler_liste = [] self.secilen_grub_liste = [] def talimat_dizin_doldur(self, url): url = os.path.split(url)[0] self.dizin_listesi.clear() for i in os.listdir(url): if os.path.isfile(url + os.sep + i): db = QMimeDatabase() db_1 = db.mimeTypeForFile(url + os.sep + i) mime_tipi = db_1.name() if mime_tipi != None: iconTipi = mime_tipi.replace("/", "-") icon = QIcon().fromTheme(iconTipi) lm = QListWidgetItem(icon, i) self.dizin_listesi.addItem(lm) def talimat_dizin_ac(self, tiklanan): url = os.path.split( self.acilan_url.text())[0] + os.sep + tiklanan.text() te_pencere = TextEditor(url, self) te_pencere.show() def dosya_olustur(self): if self.acilan_url.text() != "": dosya_olustur_pencere = DosyaOlusturSinif(self) dosya_olustur_pencere.show() else: QMessageBox.warning(self, "Hata", "Lütfen bir talimat açınız") def dosya_adi_degis(self): secilen = self.dizin_listesi.currentItem() if secilen != None: de_pencere = DosyaAdiDegisSinif(secilen.text(), self) de_pencere.show() else: QMessageBox.warning(self, "Hata", "Bir dosya seçiniz") def oku(self, url): if os.path.exists(url): self.temizle() self.talimat_dizin_doldur(url) f = open(url, "r") okunan = f.readlines() f.close() build = "" self.acilan_sozluk = {} kaynak_durum = False kaynak_tum = [] for i in okunan: if i[:5] == "isim=": isim = i[5:-1].replace(" ", "") self.program_ad.setText(isim) self.acilan_sozluk["isim"] = isim elif i[:6] == "surum=": surum = i[6:-1].replace(" ", "") self.program_surum.setText(surum) self.acilan_sozluk["surum"] = surum elif i[:6] == "devir=": devir = i[6:-1].replace(" ", "") self.program_devir.setText(devir) self.acilan_sozluk["devir"] = devir elif i[:8] == "kaynak=(": if i[-2] == ")": kaynak = i[8:-2].replace(" ", "").replace("\t", "").replace( "\n", "") self.program_kaynak.setText(kaynak) self.acilan_sozluk["kaynak"] = kaynak else: kaynak = i[8:].replace(" ", "").replace("\t", "").replace( "\n", "") kaynak_tum.append(kaynak) kaynak_durum = True elif i[:8] == "# Tanım:": if i[9] == " ": tanim = i[9:-1] else: tanim = i[8:-1] self.program_tanim.setText(tanim) self.acilan_sozluk["tanım"] = tanim elif i[:6] == "# URL:": url_ = i[6:-1].replace(" ", "") self.program_url.setText(url_) self.acilan_sozluk["url"] = url_ elif i[:10] == "# Paketçi:": paketci = i[10:-1].replace(" ", "") self.program_paketci.setText(paketci) self.acilan_sozluk["paketci"] = paketci elif i[:7] == "# Grup:": if i[7:-1] != "\n" and i[7:-1] != " " and i[7:-1] != "": for x in i[7:-1].split(" "): if x != "" and x != " ": self.secilen_grub_liste.append(x) self.program_grup.addItems(self.secilen_grub_liste) self.acilan_sozluk["grup"] = " ".join( self.secilen_grub_liste) elif i[:11] == "# Gerekler:": if i[11:-1] != "\n" and i[11:-1] != " " and i[11:-1] != "": for x in i[11:-1].split(" "): if x != "" and x != " ": self.gerek_ekle_fonk(x) elif kaynak_durum: kaynak = i.replace(" ", "").replace("\t", "") if i[-2] == ")": kaynak = kaynak.replace("\n", "")[:-1] kaynak_tum.append(kaynak) kaynak_durum = False self.program_kaynak.setText("\n".join(kaynak_tum)) self.acilan_sozluk["kaynak"] = " ".join(kaynak_tum) else: kaynak_tum.append(kaynak[:-1]) else: if i != "\n": build += i self.acilan_sozluk["build"] = build self.program_build.setText(build) def gerek_ekle_fonk(self, gerek): if gerek not in self.secilen_gerekler_liste: self.secilen_gerekler.addItem(gerek) self.secilen_gerekler_liste.append(gerek) def gerek_doldur_fonk(self, dizin): if not os.path.exists(dizin): QMessageBox.warning( self, "Hata", "Sisteminizdeki paketler okunamadı. Milis kullanmıyor olabilirsiniz." ) elif dizin[-17:] != 'talimatname/genel' and dizin[ -18:] != 'talimatname/genel/': QMessageBox.warning( self, "Hata", "talimatname/genel benzeri bir dizin beklenmekte.") else: dizindekiler = os.listdir(dizin) for i in dizindekiler: for x in os.listdir(dizin + os.sep + i): self.var_olan_gerekler_liste.append(str(x)) self.var_olan_gerekler_liste.sort() self.var_olan_gerekler.addItems(self.var_olan_gerekler_liste)
class MainWindow(QWidget): # 현재 선택된 종목(이름, 코드) stock_now = None stock_now_code = None # 키움증권 API connect = None # 트레이아이콘 tray = None # fonts font_lab_n = QFont("나눔고딕", 10) font_btn1_n = QFont("나눔바탕", 12) __ListItem = [] def __init__(self, parent=None): super(MainWindow, self).__init__(parent) self.server_connect() self.initUI() self.load_init_data() def initUI(self): # call Tray Icon self.tray = SystemTrayIcon(QIcon('C:/Users/chess/Documents/projects/StockAdvisorSystem/Images/favicon.png'), self) self.tray.show() # QAction list # 1) common viewAction = QAction("종목 조회", self) # 2) FavoriteList removeAction = QAction("제거", self) # QLabels list self.sel = QLabel("종목 검색") self.sel.setFont(self.font_lab_n) self.fav = QLabel("관심 종목") self.fav.setFont(self.font_lab_n) self.info = QLabel("종목 정보") self.info.setFont(self.font_lab_n) # QlineEdit list self.search = QLineEdit(self) # ListView and setting self.list_s = QListWidget(self) self.list_s.resize(300, 500) self.list_s.setEditTriggers(QAbstractItemView.NoEditTriggers) self.list_s.setContextMenuPolicy(QtCore.Qt.ActionsContextMenu) self.list_s.addAction(viewAction) self.list_s.addAction(removeAction) # QTableWidget and setting self.table_info_stock = QTableWidget(self) self.table_info_stock.resize(300, 500) self.table_info_stock.setRowCount(23) self.table_info_stock.setColumnCount(2) self.table_info_stock.verticalHeader().setVisible(False) self.table_info_stock.horizontalHeader().setVisible(False) self.table_info_stock.setEditTriggers(QAbstractItemView.NoEditTriggers) self.table_info_stock.setContextMenuPolicy(QtCore.Qt.ActionsContextMenu) self.table_info_stock.setItem(0, 0, QTableWidgetItem("현재가")) self.table_info_stock.setItem(1, 0, QTableWidgetItem("시가")) self.table_info_stock.setItem(2, 0, QTableWidgetItem("고가")) self.table_info_stock.setItem(3, 0, QTableWidgetItem("저가")) self.table_info_stock.setItem(4, 0, QTableWidgetItem("거래량")) self.table_info_stock.setItem(5, 0, QTableWidgetItem("거래대비")) self.table_info_stock.setItem(6, 0, QTableWidgetItem("상한가")) self.table_info_stock.setItem(7, 0, QTableWidgetItem("하한가")) self.table_info_stock.setItem(8, 0, QTableWidgetItem("기준가")) self.table_info_stock.setItem(9, 0, QTableWidgetItem("전일대비")) self.table_info_stock.setItem(10, 0, QTableWidgetItem("액면가")) self.table_info_stock.setItem(11, 0, QTableWidgetItem("연중최고")) self.table_info_stock.setItem(12, 0, QTableWidgetItem("연중최저")) self.table_info_stock.setItem(13, 0, QTableWidgetItem("등락율")) self.table_info_stock.setItem(14, 0, QTableWidgetItem("ROE")) self.table_info_stock.setItem(15, 0, QTableWidgetItem("PER")) self.table_info_stock.setItem(16, 0, QTableWidgetItem("PBR")) self.table_info_stock.setItem(17, 0, QTableWidgetItem("EV")) self.table_info_stock.setItem(18, 0, QTableWidgetItem("BPS")) self.table_info_stock.setItem(19, 0, QTableWidgetItem("시가총액")) self.table_info_stock.setItem(20, 0, QTableWidgetItem("상장주식수")) self.table_info_stock.setItem(21, 0, QTableWidgetItem("외인소진률")) self.table_info_stock.setItem(22, 0, QTableWidgetItem("자본금")) # Buttons list self.setter_Stocks = QPushButton("추가") self.setter_Stocks.setFont(self.font_btn1_n) self.setter_Stocks.setIcon(QIcon('./Images/add.png')) self.setter_Stocks.clicked.connect(self.add_favorite_event) self.remove_stocks = QPushButton("제거") self.remove_stocks.setFont(self.font_btn1_n) self.remove_stocks.setIcon(QIcon('./Images/remove.png')) self.remove_stocks.clicked.connect(self.remove_favorite_event) self.load_stocks = QPushButton("종목 조회") self.load_stocks.setFont(self.font_btn1_n) self.load_stocks.clicked.connect(self.load_favorite_event) self.setting = QPushButton("설정..") self.setting.setFont(self.font_btn1_n) self.setting.setIcon(QIcon('./Images/edit.png')) self.setting.clicked.connect(self.option_event) self.search_btn = QPushButton("검색") self.search_btn.setFont(self.font_btn1_n) self.search_btn.clicked.connect(self.search_event) self.window_trade = QPushButton("주식 거래") self.window_trade.setFont(self.font_btn1_n) self.window_trade.clicked.connect(self.trade_event) self.window_port = QPushButton("현재 종목 분석") self.window_port.setFont(self.font_btn1_n) self.window_port.clicked.connect(self.more_info_event) # Layout list vbox_l_btn = QHBoxLayout() # left LayoutBox vbox_l_btn.addWidget(self.setter_Stocks) vbox_l_btn.addWidget(self.remove_stocks) vbox_l_btn.addWidget(self.load_stocks) vbox_l_btn.addWidget(self.setting) vbox_l_search = QHBoxLayout() vbox_l_search.addWidget(self.search) vbox_l_search.addWidget(self.search_btn) vbox_l = QVBoxLayout() vbox_l.addWidget(self.sel) vbox_l.addLayout(vbox_l_search) vbox_l.addWidget(self.fav) vbox_l.addWidget(self.list_s) vbox_l.addLayout(vbox_l_btn) vbox_r_btn = QHBoxLayout() # Right LayoutBox vbox_r_btn.addWidget(self.window_trade) vbox_r_btn.addWidget(self.window_port) vbox_r = QVBoxLayout() vbox_r.addWidget(self.info) vbox_r.addWidget(self.table_info_stock) vbox_r.addLayout(vbox_r_btn) hbox = QHBoxLayout() hbox.addLayout(vbox_l) hbox.addStretch(1) hbox.addLayout(vbox_r) self.setLayout(hbox) # extra setting self.setWindowIcon(QIcon("./Images/favicon.png")) self.setWindowTitle("Stock Advisor System") self.setContextMenuPolicy(QtCore.Qt.ActionsContextMenu) self.move(300, 300) self.setFixedSize(self.size()) #Events def closeEvent(self, closeEvent=QCloseEvent()): # window close event self.hide() self.tray.showMessage("작동 중", "StockAdvisorSystem을 종료해도 트레이아이콘으로 남아있게 됩니다.\n완전한 종료를 원하신다면 아이콘 우클릭 > 종료 버튼을 눌러주세요.", 1, 50) closeEvent.ignore() def add_favorite_event(self): # add버튼을 누르면 종목을 추가하는 로직 실행 text, ok = QInputDialog.getText(self, 'add', "종목번호를 입력") if ok: try: # OpenAPI+ add favorite Event self.connect.OnReceiveTrData.connect(self.search_favorite_data) # SetInputValue self.connect.dynamicCall("SetInputValue(QString, QString)", "종목코드", text) # CommRqData self.connect.dynamicCall("CommRqData(QString, QString, int, QString)", "opt10001_req", "opt10001", 0, "0101") add = QMessageBox.question(self, '관심종목 추가', "현재 조회중인 종목:"+self.stock_now+"("+self.stock_now_code+")"+"\n추가하시겠습니까?", QMessageBox.Yes | QMessageBox.No, QMessageBox.No) if add == QMessageBox.Yes: with open("Data/InitData.txt", "a", encoding='UTF8') as f: f.write("\n "+self.stock_now+"("+self.stock_now_code+")") item = QListWidgetItem(self.list_s) item.setText(self.stock_now) self.list_s.addItem(item) elif add == QMessageBox.No: return except AttributeError as e: QMessageBox.warning(self, 'Warning', "종목을 선택해 주세요!", QMessageBox.Ok) def remove_favorite_event(self): try: rem = QMessageBox.question(self, '관심종목 제거', "현재 선택된 종목:"+self.list_s.currentItem().text()+"\n목록에서 제거하시겠습니까?", QMessageBox.Yes | QMessageBox.No, QMessageBox.No) if rem == QMessageBox.Yes: listOfFile = [] search_str = "\n "+self.list_s.currentItem().text() # 설정파일에서 지우기 with open("Data/InitData.txt", "r+", encoding='UTF8') as f: for line in f: if line.lower().find(search_str) != -1: listOfFile.append("") else: res = line.strip() res = res.strip("\n") listOfFile.append(res) with open("Data/InitData.txt", "w", encoding='UTF8') as f: for line in listOfFile: if line == "": continue elif line == "list:": f.writelines("%s\n" % line) else: f.writelines(" %s\n" % line) # 현재 목록에서 지우기 # self.list_s.removeItemWidget() elif rem == QMessageBox.No: return except AttributeError as e: QMessageBox.warning(self, 'Warning', "종목을 선택해 주세요!", QMessageBox.Ok) def load_favorite_event(self): try: # 괄호 안의 종목번호 추출 name = self.list_s.currentItem().text() res = re.findall('\(([^)]+)', name) try: # OpenAPI+ Search Event self.connect.OnReceiveTrData.connect(self.recieveData) except AttributeError as e: QMessageBox.warning(self, 'Warning', "API 서버에 연결되어있지 않습니다. 설정>서버 연결 확인 버튼을 눌러 서버에 연결해 주세요.", QMessageBox.Ok) return # SetInputValue self.connect.dynamicCall("SetInputValue(QString, QString)", "종목코드", res) # CommRqData self.connect.dynamicCall("CommRqData(QString, QString, int, QString)", "opt10001_req", "opt10001", 0, "0101") except AttributeError as e: QMessageBox.warning(self, 'Warning', "종목을 선택해 주세요!", QMessageBox.Ok) def search_event(self): if self.search.text() == "" or self.search.text() == None: QMessageBox.warning(self, 'Warning', "검색어를 입력해 주세요!", QMessageBox.Ok) return name = self.search.text() try: # OpenAPI+ Search Event self.connect.OnReceiveTrData.connect(self.recieveData) except AttributeError as e: QMessageBox.warning(self, 'Warning', "API 서버에 연결되어있지 않습니다. 설정>서버 연결 확인 버튼을 눌러 서버에 연결해 주세요.", QMessageBox.Ok) return # SetInputValue self.connect.dynamicCall("SetInputValue(QString, QString)", "종목코드", name) # CommRqData self.connect.dynamicCall("CommRqData(QString, QString, int, QString)", "opt10001_req", "opt10001", 0, "0101") def recieveData(self, screen_no, rqname, trcode, recordname, prev_next, data_len, err_code, msg1, msg2): # 출력 요소 변수명 # name : 종목명 # code : 종목코드 # price : 현재가 # market_price : 시가 # high_price : 고가 # low_price : 저가 # volume : 거래량 # preparation : 거래대비 # upper_limit : 상한가 # lower_limit : 하한가 # center_limit : 기준가 # prev_per : 전일대비 # face_value : 액면가 # high_year : 연중최고 # low_year : 연중최저 # rate : 등락율 # roe : ROE # per : PER # pbr : PBR # ev : EV # bps : BPS # market_cap : 시가총액 # listed_shares : 상장주식수 # foreigner_per : 외인소진률 # capital : 자본금 if err_code == None: print("오류!", err_code) return if rqname == "opt10001_req": result = [] result.append(self.connect.dynamicCall("CommGetData(QString, QString, QString, int, QString)", trcode, "", rqname, 0, "종목명")) result.append(self.connect.dynamicCall("CommGetData(QString, QString, QString, int, QString)", trcode, "", rqname, 0, "종목코드")) result.append(self.connect.dynamicCall("CommGetData(QString, QString, QString, int, QString)", trcode, "", rqname, 0, "시가")) result.append(self.connect.dynamicCall("CommGetData(QString, QString, QString, int, QString)", trcode, "", rqname, 0, "고가")) result.append(self.connect.dynamicCall("CommGetData(QString, QString, QString, int, QString)", trcode, "", rqname, 0, "저가")) result.append(self.connect.dynamicCall("CommGetData(QString, QString, QString, int, QString)", trcode, "", rqname, 0, "거래량")) result.append(self.connect.dynamicCall("CommGetData(QString, QString, QString, int, QString)", trcode, "", rqname, 0, "거래대비")) result.append(self.connect.dynamicCall("CommGetData(QString, QString, QString, int, QString)", trcode, "", rqname, 0, "상한가")) result.append(self.connect.dynamicCall("CommGetData(QString, QString, QString, int, QString)", trcode, "", rqname, 0, "하한가")) result.append(self.connect.dynamicCall("CommGetData(QString, QString, QString, int, QString)", trcode, "", rqname, 0, "기준가")) result.append(self.connect.dynamicCall("CommGetData(QString, QString, QString, int, QString)", trcode, "", rqname, 0, "현재가")) result.append(self.connect.dynamicCall("CommGetData(QString, QString, QString, int, QString)", trcode, "", rqname, 0, "전일대비")) result.append(self.connect.dynamicCall("CommGetData(QString, QString, QString, int, QString)", trcode, "", rqname, 0, "액면가")) result.append(self.connect.dynamicCall("CommGetData(QString, QString, QString, int, QString)", trcode, "", rqname, 0, "연중최고")) result.append(self.connect.dynamicCall("CommGetData(QString, QString, QString, int, QString)", trcode, "", rqname, 0, "연중최저")) result.append(self.connect.dynamicCall("CommGetData(QString, QString, QString, int, QString)", trcode, "", rqname, 0, "등락율")) result.append(self.connect.dynamicCall("CommGetData(QString, QString, QString, int, QString)", trcode, "", rqname, 0, "ROE")) result.append(self.connect.dynamicCall("CommGetData(QString, QString, QString, int, QString)", trcode, "", rqname, 0, "PER")) result.append(self.connect.dynamicCall("CommGetData(QString, QString, QString, int, QString)", trcode, "", rqname, 0, "PBR")) result.append(self.connect.dynamicCall("CommGetData(QString, QString, QString, int, QString)", trcode, "", rqname, 0, "EV")) result.append(self.connect.dynamicCall("CommGetData(QString, QString, QString, int, QString)", trcode, "", rqname, 0, "BPS")) result.append(self.connect.dynamicCall("CommGetData(QString, QString, QString, int, QString)", trcode, "", rqname, 0, "시가총액")) result.append(self.connect.dynamicCall("CommGetData(QString, QString, QString, int, QString)", trcode, "", rqname, 0, "상장주식수")) result.append(self.connect.dynamicCall("CommGetData(QString, QString, QString, int, QString)", trcode, "", rqname, 0, "외인소진률")) result.append(self.connect.dynamicCall("CommGetData(QString, QString, QString, int, QString)", trcode, "", rqname, 0, "자본금")) self.stock_now = result[0].strip() self.stock_now_code = result[1].strip() self.info.setText("종목 정보("+self.stock_now+"("+self.stock_now_code+")"+")") setting = [] for j in range(2, len(result)): if '+' in result[j]: tmp = QTableWidgetItem("▲"+result[j].strip().lstrip("+").lstrip("0")) tmp.setForeground(QBrush(QColor(255, 0, 0))) setting.append(tmp) elif '-' in result[j]: tmp = QTableWidgetItem("▼"+result[j].strip().lstrip("-").lstrip("0")) tmp.setForeground(QBrush(QColor(0, 0, 255))) setting.append(tmp) else: tmp = QTableWidgetItem(result[j].strip().lstrip("+").lstrip("-").lstrip("0")) tmp.setForeground(QBrush(QColor(0, 0, 0))) setting.append(tmp) for k in range(0, len(setting)): self.table_info_stock.setItem(k, 1, QTableWidgetItem(setting[k])) def search_favorite_data(self, screen_no, rqname, trcode, recordname, prev_next, data_len, err_code, msg1, msg2): if err_code == None: print("오류!", err_code) return if rqname == "opt10001_req": res_name = self.connect.dynamicCall("CommGetData(QString, QString, QString, int, QString)", trcode, "", rqname, 0, "종목명") res_code = self.connect.dynamicCall("CommGetData(QString, QString, QString, int, QString)", trcode, "", rqname, 0, "종목코드") self.stock_now = res_name.strip() self.stock_now_code = res_code.strip() def option_event(self): optionDlog = OptionDialog(self, self.connect) optionDlog.show() def trade_event(self): trade = TradeWindow(self, connect=self.connect, tray=self.tray) trade.show() def more_info_event(self): info = InfoWindow(self, code=self.stock_now) info.show() #initialize method def server_connect(self): try: self.connect = QAxWidget("KHOPENAPI.KHOpenAPICtrl.1") self.connect.dynamicCall("CommConnect()") self.connect.OnEventConnect.connect(self.event_connect) except AttributeError as e: QMessageBox.critical(self, 'Program execution error!', "실행에 실패했습니다! 32비트 가상환경을 설정 후 실행해 주세요!", QMessageBox.Ok) exit(-10) def event_connect(self, err_code): if err_code == 0: print("로그인 성공") self.tray.showMessage("로그인", "StockAdvisor가 서버에 로그인 했습니다.", 1, 10000) def load_init_data(self): # 설정파일을 불러옴 # 1. load list in left window with open("./Data/InitData.txt", 'r', encoding='UTF8') as f: for line in f: if line != "list:\n": self.__ListItem.append(line.strip()) for l in self.__ListItem: item = QListWidgetItem(self.list_s) item.setText(l.strip()) self.list_s.addItem(item)
class MainWindow(QWidget): def __init__(self, parent=None): super(MainWindow, self).__init__(parent) self.setWindowTitle("Tranquility Music Player") self.setWindowIcon(QIcon('Images/music.ico')) self.setGeometry(300, 300, 500, 400) # Create the menubar mainMenu = self.menuBar() fileMenu = mainMenu.addMenu('File') playlistMenu = mainMenu.addMenu('Playlist') viewMenu = mainMenu.addMenu('View') helpMenu = mainMenu.addMenu('Help') openFile = QAction('Open File', self) createPlaylist = QAction('Create Playlist', self) savePlaylist = QAction('Save Playlist', self) toggleTheme = QAction('Toggle Black/White Theme', self) colorTheme = QAction('Toggle Red/ Purple Theme', self) about = QAction('About Tranquility MP', self) # Establish Context Menu actions self.playlistAdd = QAction('Add to Playlist', self) self.playlistDel = QAction('Remove from Playlist', self) self.delPlaylist = QAction('Delete Playlist', self) fileMenu.addAction(openFile) playlistMenu.addAction(createPlaylist) playlistMenu.addAction(savePlaylist) viewMenu.addAction(toggleTheme) viewMenu.addAction(colorTheme) helpMenu.addAction(about) openFile.triggered.connect(self.open_file) createPlaylist.triggered.connect(self.createPlaylist) savePlaylist.triggered.connect(self.savePlaylist) colorTheme.triggered.connect(self.toggleColor) toggleTheme.triggered.connect(self.toggleTheme) about.triggered.connect(self.about) self.playlistAdd.triggered.connect(self.open_file) self.playlistDel.triggered.connect(self.removeFromPlaylist) self.delPlaylist.triggered.connect(self.deletePlaylist) self.show() def establishLayout(self): cWid = QWidget() self.setCentralWidget(cWid) self.currentPlaylist = QListWidget() self.currentPlaylist.setFocusPolicy(Qt.NoFocus) self.currentPlaylist.itemDoubleClicked.connect(self.currentSelection) self.currentPlaylist.setContextMenuPolicy(Qt.ActionsContextMenu) self.currentPlaylist.addAction(self.playlistAdd) self.currentPlaylist.addAction(self.playlistDel) self.playlistView = QListWidget() self.playlistView.adjustSize() self.playlistView.setMaximumWidth(100) self.playlistView.setContextMenuPolicy(Qt.ActionsContextMenu) self.playlistView.addAction(self.delPlaylist) self.playlistView.itemDoubleClicked.connect(self.parsePlaylist) self.seekSlider = QSlider(Qt.Horizontal) self.currentTimeLabel = QLabel('00:00') self.totalTimeLabel = QLabel('00:00') self.seekSlider.setRange(0, self.mediaPlayer.duration() / 1000) self.seekSlider.sliderMoved.connect(self.seek) self.seekSlider.valueChanged.connect(self.mediaPlayer.setPosition) # Set up splitter layout to hold the display widgets displaySplitter = QSplitter() displaySplitter.addWidget(self.playlistView) displaySplitter.addWidget(self.currentPlaylist) # Set up layout to hold the splitter layout displayLayout = QHBoxLayout() displayLayout.addWidget(displaySplitter) # Set up layout for Playlist Controls controls = PlaylistControls() controls.setState(self.mediaPlayer.state()) controls.setVolume(self.mediaPlayer.volume()) controls.setMuted(self.mediaPlayer.isMuted()) controls.play.connect(self.mediaPlayer.play) controls.pause.connect(self.mediaPlayer.pause) controls.stop.connect(self.mediaPlayer.stop) controls.next.connect(self.playlist.next) controls.previous.connect(self.previousMedia) controls.changeVolume.connect(self.mediaPlayer.setVolume) controls.muteVolume.connect(self.mediaPlayer.setMuted) controls.shuffle.connect(self.playlist.shuffle) controls.repeatAll.connect(self.setRepeatAll) controls.repeatOne.connect(self.setRepeatOne) self.mediaPlayer.stateChanged.connect(controls.setState) self.mediaPlayer.volumeChanged.connect(controls.setVolume) self.mediaPlayer.mutedChanged.connect(controls.setMuted) controlLayout = QHBoxLayout() controlLayout.addWidget(controls) # Set up layout for Seek controls seekLayout = QHBoxLayout() seekLayout.addWidget(self.currentTimeLabel) seekLayout.addWidget(self.seekSlider) seekLayout.addWidget(self.totalTimeLabel) mainLayout = QVBoxLayout() layoutHelp(mainLayout, (displayLayout, seekLayout, controlLayout)) mainLayout.setSpacing(0) self.setLayout(mainLayout) cWid.setLayout(mainLayout) if not self.mediaPlayer.isAvailable(): QMessageBox.warning(self, "Service not available") controls.setEnabled(False) self.currentPlaylist.setEnabled(False) self.metaDataChanged() self.statusBar() def open_file(self): fileNames, _ = QFileDialog.getOpenFileNames(self, "Open Files", "C:\\Users\\dchtk\\Music", 'All Files(*.*)') self.addToPlaylist(fileNames) def currentSelection(self): currentSelection = self.currentPlaylist.currentRow() self.playlist.setCurrentIndex(currentSelection) self.mediaPlayer.play() def removeFromPlaylist(self): selectedTrack = self.currentPlaylist.currentRow() self.playlist.setCurrentIndex(selectedTrack) self.currentPlaylist.takeItem(selectedTrack) self.playlist.removeMedia(selectedTrack) def deletePlaylist(self): selectedPlaylist = self.playlistView.currentRow() self.playlistView.takeItem(selectedPlaylist) def parsePlaylist(self, lines=None): path = "C:\\Users\dchtk\\Music\\Playlists" arr = os.listdir(path) for x in arr: xpath = os.path.join(path, x) if self.playlistView.selectedItems()[0].text() in xpath: item = xpath plFile = open(item, 'r') if plFile.mode == "r": songs = plFile.read() if self.currentPlaylist.count() > 0: self.currentPlaylist.clear() self.currentPlaylist.addItem(songs) else: self.currentPlaylist.addItem(songs) def about(self): QMessageBox.information( self, "About Tranquility MP", "Tranquility Media Player Version 1.0,\n\n" "Developed by: D. Chaitkin")