an open source ide which has a style and look of a vs code but has the power and functionality that is provided in pycharm
from PyQt5.QtWidgets import QPlainTextEdit, QFrame, QVBoxLayout, QWidget
from PyQt5.QtCore import Qt
from .syntax_highlighter import SyntaxHighlighter
from .line_numbers import LineNumberArea
from PyQt5.QtGui import QPainter

class CodeEditor(QFrame):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.initUI()

    def initUI(self):
        # Create a layout for the code editor and line numbers
        layout = QVBoxLayout(self)
        layout.setContentsMargins(0, 0, 0, 0)

        # Create the code editor widget
        self.code_editor = QPlainTextEdit(self)
        self.code_editor.setLineWrapMode(QPlainTextEdit.NoWrap)

        # Create a syntax highlighter for the code editor
        self.highlighter = SyntaxHighlighter(self.code_editor.document())

        # Add code editor to the layout
        layout.addWidget(self.code_editor)

        # Create the line numbers widget
        self.line_numbers = LineNumberArea(self.code_editor)

        # Set the code editor's viewport margin to the width of the line numbers
        self.code_editor.setViewportMargins(self.line_numbers.width(), 0, 0, 0)

        # Connect the code editor's scrollbar to update the line numbers
        self.code_editor.verticalScrollBar().valueChanged.connect(self.update_line_numbers)

        # Initialize line numbers
        self.init_line_numbers()

        self.setLayout(layout)

    def init_line_numbers(self):
        self.code_editor.verticalScrollBar().valueChanged.connect(self.line_numbers.update)

    def line_number_width(self):
        digits = 1
        max_value = max(1, self.code_editor.blockCount())
        while max_value >= 10:
            max_value /= 10
            digits += 1
        space = 3 + self.code_editor.fontMetrics().width('9') * digits
        return space

    def line_number_paint(self, event):
        painter = QPainter(self.line_numbers)
        painter.fillRect(event.rect(), Qt.lightGray)
        block = self.code_editor.firstVisibleBlock()
        block_number = block.blockNumber()
        top = self.code_editor.blockBoundingGeometry(block).translated(self.code_editor.contentOffset()).top()
        bottom = top + self.code_editor.blockBoundingRect(block).height()

        # Iterate over visible blocks and paint line numbers
        while block.isValid() and (top <= event.rect().bottom()):
            if block.isVisible() and (bottom >= event.rect().top()):
                number = str(block_number + 1)
                painter.setPen(Qt.black)
                painter.drawText(0, top, self.line_numbers.width(), self.code_editor.fontMetrics().height(), Qt.AlignRight, number)
            block = block.next()
            top = bottom
            bottom = top + self.code_editor.blockBoundingRect(block).height()
            block_number += 1
        painter.end()

    def update_line_numbers(self):
        self.line_numbers.update()

components/code_editor/code_editor.py
rohitagr0310/dw-code
from PyQt5.QtWidgets import QWidget
from PyQt5.QtCore import QSize, Qt
from PyQt5.QtGui import QPainter

class LineNumberArea(QWidget):
    def __init__(self, editor):
        super().__init__(editor)
        self.code_editor = editor

    def sizeHint(self):
        return QSize(self.line_number_width(), 0)

    def line_number_width(self):
        digits = len(str(self.code_editor.blockCount()))
        space = 3 + self.fontMetrics().width('9') * digits
        return space

    def paintEvent(self, event):
        painter = QPainter(self)
        painter.fillRect(event.rect(), Qt.lightGray)
        block = self.code_editor.firstVisibleBlock()
        block_number = block.blockNumber() + 1
        top = self.code_editor.blockBoundingGeometry(block).translated(self.code_editor.contentOffset()).top()
        bottom = top + self.code_editor.blockBoundingRect(block).height()

        while block.isValid() and top <= event.rect().bottom():
            if block.isVisible() and bottom >= event.rect().top():
                text = str(block_number)
                painter.setPen(Qt.black)
                painter.drawText(0, top, self.width(), self.fontMetrics().height(), Qt.AlignRight | Qt.AlignVCenter, text)
            block = block.next()
            top = bottom
            bottom = top + self.code_editor.blockBoundingRect(block).height()
            block_number += 1

components/code_editor/line_numbers.py
rohitagr0310/dw-code
from PyQt5.QtGui import QTextCharFormat, QTextDocument
from PyQt5.QtWidgets import QPlainTextEdit
from PyQt5.QtGui import QSyntaxHighlighter, QSyntaxHighlighter
from PyQt5.QtCore import Qt, QTextStream
from traitlets import CRegExp

class SyntaxHighlighter(QSyntaxHighlighter):
    def __init__(self, parent):
        super().__init__(parent)
        self.highlighting_rules = []

        # Define highlighting rules (e.g., for keywords, comments, etc.)

    def highlightBlock(self, text):
        for pattern, format in self.highlighting_rules:
            regex = CRegExp(pattern)
            iterator = regex.globalMatch(text)
            while iterator.hasNext():
                match = iterator.next()
                self.setFormat(match.capturedStart(), match.capturedLength(), format)

components/code_editor/syntax_highlighter.py
rohitagr0310/dw-code
from PyQt5.QtWidgets import QMainWindow, QMenuBar, QMenu, QAction

def create_menu_bar(root):
    menubar = root.menuBar()

    # Create a "File" menu
    file_menu = menubar.addMenu("File")

    # Add menu items to the "File" menu
    new_action = QAction("New", root)
    open_action = QAction("Open", root)
    save_action = QAction("Save", root)
    save_as_action = QAction("Save As", root)
    exit_action = QAction("Exit", root)

    file_menu.addAction(new_action)
    file_menu.addAction(open_action)
    file_menu.addAction(save_action)
    file_menu.addAction(save_as_action)
    file_menu.addSeparator()  # Add a separator line
    file_menu.addAction(exit_action)

    # Connect menu items to functions or actions as needed
    # For example, exit_action.triggered.connect(on_exit)

components/menu_bar/menu_bar.py
rohitagr0310/dw-code
import sys
from PyQt5.QtWidgets import QApplication, QMainWindow
from components.code_editor.code_editor import CodeEditor
from components.menu_bar.menu_bar import create_menu_bar

def create_base_window():
    app = QApplication(sys.argv)
    root = QMainWindow()
    root.setWindowTitle("My Python IDE")
    root.setGeometry(100, 100, 800, 600)  # Set the window size

    # Create the custom code editor component
    code_editor = CodeEditor(root)
    root.setCentralWidget(code_editor)

    # Create the menu bar
    create_menu_bar(root)

    return app, root

if __name__ == "__main__":
    app, main_window = create_base_window()
    main_window.show()
    sys.exit(app.exec_())

main.py
rohitagr0310/dw-code