0% found this document useful (0 votes)
8 views11 pages

Main Window Py 7n

The document outlines the implementation of a PyQt5 application called 'NVivo Clone', which serves as a tagging and document management tool. It features a user interface with tabs for document editing, a tagging panel, and various menu options for file management and theme toggling. Additionally, it includes functionality for auto-saving documents, displaying project statistics, and visualizing data through charts.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
8 views11 pages

Main Window Py 7n

The document outlines the implementation of a PyQt5 application called 'NVivo Clone', which serves as a tagging and document management tool. It features a user interface with tabs for document editing, a tagging panel, and various menu options for file management and theme toggling. Additionally, it includes functionality for auto-saving documents, displaying project statistics, and visualizing data through charts.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 11

import os

import json

import matplotlib.pyplot as plt

from PyQt5.QtWidgets import (

QMainWindow, QWidget, QTextEdit, QListWidget, QPushButton,

QVBoxLayout, QHBoxLayout, QFileDialog, QAction, QMessageBox,

QLineEdit, QTabWidget, QLabel

from PyQt5.QtCore import Qt, QTimer

from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as


FigureCanvas

from database.models import session, Tag, Project, Document

class MainWindow(QMainWindow):

def __init__(self):

super().__init__()

self.setWindowTitle("NVivo Clone")

self.resize(1000, 700)

self.is_dark_mode = False

self.setup_ui()

self.create_menu()

self.load_tags()

self.start_auto_save()

def setup_ui(self):

# Document tabs

self.tabs = QTabWidget()
self.tabs.setTabsClosable(True)

self.tabs.tabCloseRequested.connect(self.close_tab)

self.add_new_tab()

# Tagging panel

self.tag_list = QListWidget()

self.tag_list.itemClicked.connect(self.apply_tag)

self.tag_input = QLineEdit()

self.tag_input.setPlaceholderText("Enter new tag")

self.add_tag_btn = QPushButton("Add Tag")

self.add_tag_btn.clicked.connect(self.add_tag)

self.search_bar = QLineEdit()

self.search_bar.setPlaceholderText("Search tags...")

self.search_bar.textChanged.connect(self.filter_tags)

tag_layout = QVBoxLayout()

tag_layout.addWidget(self.search_bar)

tag_layout.addWidget(self.tag_list)

tag_layout.addWidget(self.tag_input)

tag_layout.addWidget(self.add_tag_btn)

main_layout = QHBoxLayout()

main_layout.addLayout(tag_layout, 1)

main_layout.addWidget(self.tabs, 3)
container = QWidget()

container.setLayout(main_layout)

self.setCentralWidget(container)

self.home_tab = QWidget()

self.init_home_tab()

self.tabs.addTab(self.home_tab, "Home")

def create_menu(self):

menubar = self.menuBar()

file_menu = menubar.addMenu("File")

open_action = QAction("Open", self)

open_action.triggered.connect(self.open_file)

save_action = QAction("Save", self)

save_action.triggered.connect(self.save_file)

new_tab_action = QAction("New Tab", self)

new_tab_action.triggered.connect(self.add_new_tab)

export_action = QAction("Export Tags", self)

export_action.triggered.connect(self.export_tags)

file_menu.addAction(new_tab_action)

file_menu.addAction(open_action)

file_menu.addAction(save_action)

file_menu.addAction(export_action)
view_menu = menubar.addMenu("View")

theme_action = QAction("Toggle Theme", self)

theme_action.triggered.connect(self.toggle_theme)

view_menu.addAction(theme_action)

help_menu = menubar.addMenu("Help")

about_action = QAction("About", self)

about_action.triggered.connect(self.show_about)

help_menu.addAction(about_action)

def load_tags(self):

self.tag_list.clear()

tags = session.query(Tag).all()

for tag in tags:

self.tag_list.addItem(tag.name)

def add_tag(self):

tag_name = self.tag_input.text().strip()

if tag_name:

if not session.query(Tag).filter_by(name=tag_name).first():

new_tag = Tag(name=tag_name)

session.add(new_tag)

session.commit()

self.tag_list.addItem(tag_name)

self.tag_input.clear()

else:
QMessageBox.information(self, "Tag Exists", "This tag already
exists.")

def apply_tag(self, item):

editor = self.current_editor()

if editor:

cursor = editor.textCursor()

selected_text = cursor.selectedText()

if selected_text:

tagged_text = f"[{item.text()}:{selected_text}]"

cursor.insertText(tagged_text)

else:

QMessageBox.warning(self, "No Selection", "Please select text to


tag.")

def filter_tags(self, text):

for index in range(self.tag_list.count()):

item = self.tag_list.item(index)

item.setHidden(text.lower() not in item.text().lower())

def open_file(self):

path, _ = QFileDialog.getOpenFileName(self, "Open File", "", "Text Files


(*.txt)")

if path:

with open(path, 'r', encoding='utf-8') as file:

content = file.read()

self.add_new_tab(content, os.path.basename(path))
def save_file(self):

editor = self.current_editor()

if editor:

path, _ = QFileDialog.getSaveFileName(self, "Save File", "", "Text Files


(*.txt)")

if path:

with open(path, 'w', encoding='utf-8') as file:

file.write(editor.toPlainText())

def export_tags(self):

path, _ = QFileDialog.getSaveFileName(self, "Export Tags", "", "JSON


Files (*.json)")

if path:

tags = [tag.name for tag in session.query(Tag).all()]

with open(path, 'w', encoding='utf-8') as file:

json.dump(tags, file)

def toggle_theme(self):

self.is_dark_mode = not self.is_dark_mode

if self.is_dark_mode:

self.setStyleSheet("""

QWidget { background-color: #2b2b2b; color: #ffffff; }

QLineEdit, QTextEdit { background-color: #3c3c3c; color: #ffffff; }

QListWidget { background-color: #3c3c3c; color: #ffffff; }

""")

else:

self.setStyleSheet("")
def show_about(self):

QMessageBox.information(self, "About NVivo Clone", "NVivo Clone App\


nBuilt with Python and PyQt5\nDeveloped by Temwa")

def start_auto_save(self):

self.auto_save_timer = QTimer(self)

self.auto_save_timer.timeout.connect(self.auto_save)

self.auto_save_timer.start(60000) # 60 seconds

def auto_save(self):

for index in range(self.tabs.count()):

editor = self.tabs.widget(index).findChild(QTextEdit)

if editor:

file_path = f'autosave_tab_{index}.txt'

with open(file_path, 'w', encoding='utf-8') as file:

file.write(editor.toPlainText())

def current_editor(self):

current_widget = self.tabs.currentWidget()

return current_widget.findChild(QTextEdit) if current_widget else None

def add_new_tab(self, content="", title="Untitled"):

editor = QTextEdit()

editor.setText(content)

tab = QWidget()

layout = QVBoxLayout()
layout.addWidget(editor)

tab.setLayout(layout)

self.tabs.addTab(tab, title)

self.tabs.setCurrentWidget(tab)

def close_tab(self, index):

self.tabs.removeTab(index)

def init_home_tab(self):

layout = QVBoxLayout()

# Welcome Header

welcome_label = QLabel("Welcome to NVivoClone!", self)

welcome_label.setStyleSheet("font-size: 24px; font-weight: bold;")

layout.addWidget(welcome_label)

# Project Stats

project_count = self.session.query(Project).count()

doc_count = self.session.query(Document).count()

tag_count = self.session.query(Tag).count()

stats_label = QLabel(f"Projects: {project_count} | Documents:


{doc_count} | Tags: {tag_count}", self)

stats_label.setStyleSheet("font-size: 16px; margin-top: 10px;")

layout.addWidget(stats_label)

# Action Buttons
btn_layout = QHBoxLayout()

create_btn = QPushButton("Create Project")

create_btn.clicked.connect(self.create_project)

btn_layout.addWidget(create_btn)

open_btn = QPushButton("Open Project")

open_btn.clicked.connect(self.open_project)

btn_layout.addWidget(open_btn)

layout.addLayout(btn_layout)

# Recent Projects

recent_label = QLabel("Recent Projects:")

layout.addWidget(recent_label)

recent_projects =
self.session.query(Project).order_by(Project.id.desc()).limit(5).all()

for project in recent_projects:

doc_total = len(project.documents)

proj_label = QLabel(f"- {project.name} ({doc_total} documents)")

layout.addWidget(proj_label)

# Bar Chart - Documents per Project

if recent_projects:

names = [p.name for p in recent_projects]

counts = [len(p.documents) for p in recent_projects]


fig, ax = plt.subplots(figsize=(5, 3))

ax.bar(names, counts, color='skyblue')

ax.set_title("Documents per Recent Project")

ax.set_ylabel("Documents")

ax.set_xlabel("Projects")

ax.tick_params(axis='x', rotation=45)

canvas = FigureCanvas(fig)

layout.addWidget(canvas)

# Pie Chart - Tag Usage

tags = self.session.query(Tag).all()

tag_names = []

tag_counts = []

for tag in tags:

count =
self.session.query(Document).filter(Document.content.contains(tag.name)).c
ount()

if count > 0:

tag_names.append(tag.name)

tag_counts.append(count)

if tag_names:

fig2, ax2 = plt.subplots(figsize=(4, 3))

ax2.pie(tag_counts, labels=tag_names, autopct="%1.1f%%",


startangle=140)

ax2.set_title("Tag Usage")
canvas2 = FigureCanvas(fig2)

layout.addWidget(canvas2)

# Project Search Box

search_label = QLabel("Search Projects:")

layout.addWidget(search_label)

self.search_input = QLineEdit()

self.search_input.setPlaceholderText("Type to search projects...")

self.search_input.textChanged.connect(self.filter_projects)

layout.addWidget(self.search_input)

self.search_results = QListWidget()

layout.addWidget(self.search_results)

layout.addStretch()

self.home_tab.setLayout(layout)

def filter_projects(self, text):

self.search_results.clear()

if text.strip():

results = self.session.query(Project).filter(Project.name.ilike(f"%
{text}%")).all()

for project in results:

self.search_results.addItem(project.name)

You might also like