0

I have main class with sub-classes as tabs. I have GUI like this: gui

QApp.py - Mainwindow

#!/usr/bin/env python
# -*- coding: utf-8 -*-

from PyQt5 import QtGui, QtWidgets
from QFilesTab import Files
from QWebservicesTab import Webservices
import qdarkstyle


class MainWindow(QtWidgets.QMainWindow):
def __init__(self):
    super().__init__()

    self.task_bar()
    self.tab_layout()
    self.graph_elements()
    self.center()

def task_bar(self):
    ### actions on meenubar
    exitAct = QtWidgets.QAction('&Exit', self, shortcut='Ctrl+Q', statusTip='Exit application')
    exitAct.triggered.connect(self.close)
    moreinfo = QtWidgets.QAction('&Help', self, statusTip='More information')
    moreinfo.triggered.connect(self.information)

    ### menubar
    menubar = self.menuBar()
    fileMenu = menubar.addMenu('&File')
    fileMenu.addAction(exitAct)
    fileMenu = menubar.addMenu('&Help')
    fileMenu.addAction(moreinfo)

def graph_elements(self):
    ### basic geometry and color
    self.setWindowTitle('Villain')
    self.setWindowIcon(QtGui.QIcon('dc1.png'))
    self.setStyleSheet((qdarkstyle.load_stylesheet_pyqt5()))

def tab_layout(self):
    self.tabwidget = QtWidgets.QTabWidget()
    self.tabwidget.addTab(Files(), 'Files Import') ### ADDED SUB_CLASS AS QTABWIDGET
    self.tabwidget.addTab(Webservices(), 'Webservice')
    self.setCentralWidget(self.tabwidget)

### center main window
def center(self):
    qr = self.frameGeometry()
    cp = QtWidgets.QDesktopWidget().availableGeometry().center()
    qr.moveCenter(cp)
    self.move(qr.topLeft())

def information(self):
    QtWidgets.QMessageBox.information(self,'Information','Version: 2.0\n'\
                                        'Please, contact karol.chojnowski@digitalcaregroup.com for comments and suggestions\n\n'\
                                      'Digital Care - Data Processing Team')

This is my subclass, which i have as 'Files Import' tab on screen. I have to use credentials to connect with sql. So i ll try get it from my __main__

QFilesTab.py - subclass as qtabwidget

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import threading
from PyQt5 import QtGui, QtWidgets, QtCore
import pyodbc



class Files(QtWidgets.QWidget):
def __init__(self):
    super().__init__()
    self.layout_init()

def layout_init(self):
    operator = ['TMobile', 'PLK', 'Play', 'Orange']
    variant = ['Select variant', 'Numer usługi/polisy', 'IMEI', 'PESEL', 'NIP',
                'REGON', 'Nazwisko', 'Nazwa firmy']
    ###partners
    self.pvbox = QtWidgets.QVBoxLayout()
    self.buttongroup = QtWidgets.QButtonGroup(self)
    for elements, forms in enumerate(operator):
        element = str(forms)
        self.partners = QtWidgets.QRadioButton(element)
        self.buttongroup.addButton(self.partners, )
        self.pvbox.addWidget(self.partners,)
    self.buttongroup.buttonClicked.connect(self.on_itemSelected)
    self.buttongroup.buttonClicked['int'].connect(self.on_itemSelected)


    ###variants
    self.variants = QtWidgets.QComboBox()
    for elements, forms in enumerate(variant):
        element = str(forms)
        self.variants.addItem(element)
    self.variants.model().item(0).setEnabled(False)
    self.variants.activated.connect(self.update_textbox)

    self.textbox = QtWidgets.QLineEdit()

    self.tablewidget = QtWidgets.QTableWidget()
    self.tablewidget.setColumnCount(5)
    self.tablewidget.setHorizontalHeaderLabels(['FileNameOriginal', 'OrderItemCode', 'Imported','InfoCode', 'Row'])
    self.tablewidget.horizontalHeader().setDefaultAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter)
    self.tablewidget.horizontalHeader().setStretchLastSection(True)
    self.tablewidget.resizeColumnsToContents()
    self.tablewidget.setSelectionMode(QtWidgets.QAbstractItemView.SingleSelection)
    self.tablewidget.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers)

    self.pb = QtWidgets.QPushButton(self.tr('Run process'))
    self.pb.setDisabled(True)
    self.textbox.textChanged.connect(self.disableButton)
    self.pb.clicked.connect(self.on_clicked_pb)
    self.clearbutton = QtWidgets.QPushButton(self.tr('Clear all'))
    self.clearbutton.setDisabled(True)
    self.clearbutton.clicked.connect(self.on_clicked_clear)

    vgroupbox = QtWidgets.QGroupBox('Options')
    pgroupbox = QtWidgets.QGroupBox('Partner')

    mainpanel = QtWidgets.QBoxLayout(QtWidgets.QBoxLayout.LeftToRight)
    variantpanel = QtWidgets.QBoxLayout(QtWidgets.QBoxLayout.TopToBottom)
    variantpanel.addWidget(self.variants)
    variantpanel.addWidget(self.textbox)
    variantpanel.addWidget(self.pb)
    variantpanel.addWidget(self.clearbutton)
    mainpanel.addWidget(pgroupbox)
    mainpanel.addWidget(vgroupbox)
    vgroupbox.setLayout(variantpanel)
    test = QtWidgets.QVBoxLayout(self)
    test.addLayout(self.pvbox)
    pgroupbox.setLayout(test)

    grid = QtWidgets.QBoxLayout(QtWidgets.QBoxLayout.TopToBottom, self)
    grid.addLayout(mainpanel)
    grid.addWidget(self.tablewidget)
    self.setLayout(grid)

def setCredentials(self, credentials): ################################
    self._credentials = credentials

def update_textbox(self, text):
    self.textbox.clear()
    textline = self.variants.itemText(text)
    self.textbox.setPlaceholderText(textline)
    if textline == 'IMEI':
        regexp = QtCore.QRegExp('^(?=.{0,16}$)(0\d+|[1-9][0-9]+)$')
    elif textline == 'PESEL':
        regexp = QtCore.QRegExp('^(?=.{0,11}$)(0\d+|[1-9][0-9]+)$')
    elif textline == 'NIP':
        regexp = QtCore.QRegExp('^(?=.{0,10}$)(0\d+|[1-9][0-9]+)$')
    elif textline == 'REGON':
        regexp = QtCore.QRegExp('^(?=.{0,9}$)(0\d+|[1-9][0-9]+)$')
    elif textline == 'Nazwisko':
        regexp = QtCore.QRegExp('[A-Za-zżźćńółęąśŻŹĆĄŚĘŁÓŃ]*')
    else:
        regexp = None
    self.textbox.setValidator(QtGui.QRegExpValidator(regexp))

@QtCore.pyqtSlot(QtWidgets.QAbstractButton)
@QtCore.pyqtSlot(int)
def on_itemSelected(self, index):
    if isinstance(index, QtWidgets.QAbstractButton):
        self.base = None
        element = '{}'.format(index.text())
        if element == 'Play':
            self.base = 'W2_FileImportWorkerP4'
        elif element == 'TMobile':
            self.base= 'W2_FileImportWorkerTmobileFIX'
        elif element == 'Orange':
            self.base = 'W2_FileImportWorkerOCP'
        elif element == 'PLK':
            self.base = 'W2_FileImportWorkerPLK'
        return self.base
    elif isinstance(index, int):
        pass

@QtCore.pyqtSlot()
def disableButton(self):
    val = bool(self.textbox.text())
    self.pb.setDisabled(not val)
    self.clearbutton.setDisabled(not val)

@QtCore.pyqtSlot()
def disablesql(self):
    self.textbox.setDisabled(True)
    self.pb.setDisabled(True)
    self.clearbutton.setDisabled(True)

@QtCore.pyqtSlot()
def enablesql(self):
    self.textbox.setDisabled(False)
    self.pb.setDisabled(False)
    self.clearbutton.setDisabled(False)


### run process button
@QtCore.pyqtSlot()
def on_clicked_pb(self):
    if self.textbox.text():
        threading.Thread(target=self.sql_query, daemon=True).start()

### clear all
@QtCore.pyqtSlot()
def on_clicked_clear(self):
    if self.textbox.text():
        self.textbox.clear()
    self.tablewidget.setRowCount(0)
    self.tablewidget.setColumnWidth(3, 200)

def table_performance(self):
    self.tablewidget.resizeColumnsToContents()
    self.tablewidget.setColumnWidth(4, 2500)
    self.tablewidget.setHorizontalScrollMode(QtWidgets.QAbstractItemView.ScrollPerPixel)

@QtCore.pyqtSlot(str, str)
def show_warning(self, title, msg):
    QtWidgets.QMessageBox.information(self, title, msg)

@QtCore.pyqtSlot(str, str)
def show_ok(self, title, msg):
    QtWidgets.QMessageBox.information(self, title ,msg)

@QtCore.pyqtSlot()
def clear_items(self):
    self.tablewidget.setRowCount(0)

@QtCore.pyqtSlot(int, int, str)
def add_item(self, row, column, val):
    if row >= self.tablewidget.rowCount():
        self.tablewidget.insertRow(self.tablewidget.rowCount())
    newitem = QtWidgets.QTableWidgetItem(val)
    self.tablewidget.setItem(row, column, newitem)

@QtCore.pyqtSlot()
def sort_items(self):
    self.tablewidget.sortItems(0, order=QtCore.Qt.DescendingOrder)

def sql_query(self):
    ser = '10.96.5.17\dqinstance'
    print(self.credentials) #check
    username, pwd = self._credentials ############################
    imei = '%' + self.textbox.text() + '%'
    self.clear_items()
    try:
        self.disablesql()
        connection = pyodbc.connect(driver='{SQL Server}', server=ser,
                                    user=username, password=pwd)
        if self.base == 'W2_FileImportWorkerTmobileFIX':
            cursor = connection.cursor()
            res = cursor.execute(''' 
                                                SELECT FI.FileNameOriginal,
                                                FI.OrderItemCode,
                                                FIR.Imported,
                                                FIRI.InfoCode,
                                                FR.Row
                                                FROM BIDQ_W2_DB.dbo.[FileImports] AS FI
                                    JOIN BIDQ_W2_DB.dbo.[FileImportRows] AS FIR ON FI.Id = FIR.FileImportId
                                    JOIN BIDQ_W2_DB.dbo.[FileRows] AS FR ON FIR.RowId = FR.RowId 
                                    LEFT JOIN BIDQ_W2_DB.dbo.FileImportRowInfoes AS FIRI ON FR.RowId = FIRI.RowId
                                                WHERE (FI.WorkerCode = ? or FI.WorkerCode = ?) and FR.Row LIKE ? ''',
                                 (self.base, self.base, imei))

        elif self.base == 'All':
            cursor = connection.cursor()
            res = cursor.execute(''' SELECT FI.FileNameOriginal,
                                    FI.OrderItemCode,
                                    FIR.Imported,
                                    FIRI.InfoCode,
                                    FR.Row
                                    FROM BIDQ_W2_DB.dbo.[FileImports] AS FI
                                    JOIN BIDQ_W2_DB.dbo.[FileImportRows] AS FIR ON FI.Id = FIR.FileImportId
                                    JOIN BIDQ_W2_DB.dbo.[FileRows] AS FR ON FIR.RowId = FR.RowId 
                                    LEFT JOIN BIDQ_W2_DB.dbo.FileImportRowInfoes AS FIRI ON FR.RowId = FIRI.RowId
                                    WHERE FR.Row LIKE ? ''',(imei))
        else:
            cursor = connection.cursor()
            res = cursor.execute('''
                                    SELECT FI.FileNameOriginal,
                                    FI.OrderItemCode,
                                    FIR.Imported,
                                    FIRI.InfoCode,
                                    FR.Row
                                    FROM BIDQ_W2_DB.dbo.[FileImports] AS FI
                                    JOIN BIDQ_W2_DB.dbo.[FileImportRows] AS FIR ON FI.Id = FIR.FileImportId
                                    JOIN BIDQ_W2_DB.dbo.[FileRows] AS FR ON FIR.RowId = FR.RowId 
                                    LEFT JOIN BIDQ_W2_DB.dbo.FileImportRowInfoes AS FIRI ON FR.RowId = FIRI.RowId
                                    WHERE FI.WorkerCode =  ? and FR.Row LIKE ? ''', (self.base, imei))

        if not cursor.rowcount:
            QtCore.QMetaObject.invokeMethod(self, 'show_warning',
                                            QtCore.Qt.QueuedConnection,
                                            QtCore.Q_ARG(str, 'IMEI'), QtCore.Q_ARG(str, 'No items found'))
        else:
            QtCore.QMetaObject.invokeMethod(self, 'clear_items', QtCore.Qt.QueuedConnection)
            QtCore.QThread.msleep(10)
            for row, form in enumerate(res):
                for column, item in enumerate(form):
                    QtCore.QMetaObject.invokeMethod(self, 'add_item',
                                                    QtCore.Qt.QueuedConnection,
                                                    QtCore.Q_ARG(int, row), QtCore.Q_ARG(int, column),
                                                    QtCore.Q_ARG(str, str(item)))
                    QtCore.QThread.msleep(10)
            QtCore.QMetaObject.invokeMethod(self, 'sort_items', QtCore.Qt.QueuedConnection)
            self.table_performance()
            QtCore.QMetaObject.invokeMethod(self, 'show_ok',
                                            QtCore.Qt.QueuedConnection,
                                            QtCore.Q_ARG(str, 'Done'), QtCore.Q_ARG(str, 'Items found'))
        cursor.close()

    except:
            QtCore.QMetaObject.invokeMethod(self, 'show_warning',
                                            QtCore.Qt.QueuedConnection,
                                            QtCore.Q_ARG(str, 'Error'), QtCore.Q_ARG(str, 'Something went wrong\n\n' \
                                                                                          'Contact karol.chojnowski@digitalcaregroup.com'))
    self.enablesql()

When i try get credentials from main - got error like this : error

Im trying to pass credentials in __main__ to Files(). What is wrong? Before when I had only one main class without tabs it worked.... What is the best way to pass credentials in this case? Im asking because im goin to use these credentials in other tabs. Should I create subclass only for credentials?

# -- coding: utf-8 --

import sys
from PyQt5 import QtWidgets,QtGui
from QLogin import LoginDialog
from QApp import MainWindow
from QFilesTab import Files
import os


def resource_path(relative_path):
if hasattr(sys, '_MEIPASS'):
    return os.path.join(sys._MEIPASS, relative_path)
return os.path.join(os.path.abspath('.'), relative_path)


if __name__ == '__main__':

app = QtWidgets.QApplication(sys.argv)

login = LoginDialog()
login.setWindowIcon(QtGui.QIcon(resource_path('dc1.png')))

if login.exec_() != QtWidgets.QDialog.Accepted:
    sys.exit(-1)

files = Files()
window = MainWindow()
window.setWindowIcon(QtGui.QIcon(resource_path('dc1.png')))
window.setGeometry(500, 150, 800, 500)
files.setCredentials(login.credentials()) ###############################
window.show()
sys.exit(app.exec_())

In code i put multiple ################# when i have problematic places.

Edited:

LoginDialog

# -- coding: utf-8 --

from PyQt5.QtWidgets import QLineEdit,QDialogButtonBox,QFormLayout,QDialog,QMessageBox
from PyQt5 import QtWidgets,QtCore
import qdarkstyle
import pyodbc


class LoginDialog(QDialog):
def __init__(self, parent=None):
    super(LoginDialog,self).__init__(parent)
    self.init_ui()


def init_ui(self):
    ### delete question mark
    self.setWindowFlags(self.windowFlags()
                        ^ QtCore.Qt.WindowContextHelpButtonHint)

    ### login & password fields
    self.username = QLineEdit(self)
    self.password = QLineEdit(self)
    self.password.setEchoMode(QLineEdit.Password)

    loginLayout = QFormLayout()
    loginLayout.addRow('Username', self.username)
    loginLayout.addRow('Password', self.password)
    self.buttons = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
    self.buttons.accepted.connect(self.control)
    self.buttons.rejected.connect(self.reject)
    layout = QtWidgets.QVBoxLayout(self)
    layout.addLayout(loginLayout)
    layout.addWidget(self.buttons)
    self.setLayout(layout)

    ### set window title & stylesheet
    self.setWindowTitle('Villain - 10.96.6.14 ')
    #self.setWindowIcon(QtGui.QIcon('dc1.png'))
    self.setStyleSheet((qdarkstyle.load_stylesheet_pyqt5()))
    ###lock resize
    self.setSizeGripEnabled(False)
    self.setFixedSize(self.sizeHint())


def credentials(self):
    return self.username.text(), self.password.text()


###log by usins sql credentials
def control(self):
    ser = '10.96.5.17\dqinstance'
    login = self.username.text()
    pwd = self.password.text()

    try:
        self.connection = pyodbc.connect(driver='{SQL Server}', server=ser,
                     user=login, password=pwd)
        cursor = self.connection.cursor()
        cursor.close()
        self.accept()
    except:
        QMessageBox.warning(self, 'Error', 'Wrong username or password! \n\n'
                                           'Please use the SQL Server credentials ')
karolch
  • 184
  • 4
  • 19

1 Answers1

0

This is how I solved this:

  1. In Main.py i have passed argument from LoginDIalog class to MainWindow class. window.tab_layout(login.credentials())
  2. In QApp.py i have edited method tab_layout:

    def tab_layout(self, credentials):
        self.tabwidget = QtWidgets.QTabWidget()
        self.tabwidget.addTab(Files(credentials), 'Files Import')
        self.tabwidget.addTab(Webservices(), 'Webservice')
        self.setCentralWidget(self.tabwidget)
    
  3. In QFilesTab.py i have added to Files class constuctor self._credentials = credentials and deleted method setCredentials. Now, my sql_query method is using credentials from constuctor.

karolch
  • 184
  • 4
  • 19