├── bold.png ├── center-align.png ├── copy.png ├── cut.png ├── italic.png ├── justification.png ├── left-align.png ├── main.py ├── main_complete.py ├── paste.png ├── printing.png ├── redo.png ├── right-align.png ├── save.png ├── underline.png ├── undo.png ├── zoom-in.png └── zoom-out.png /bold.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ProgrammingHero1/BS_Word/0987e07f14ab5288ec6a9715cae36dae8a7387ae/bold.png -------------------------------------------------------------------------------- /center-align.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ProgrammingHero1/BS_Word/0987e07f14ab5288ec6a9715cae36dae8a7387ae/center-align.png -------------------------------------------------------------------------------- /copy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ProgrammingHero1/BS_Word/0987e07f14ab5288ec6a9715cae36dae8a7387ae/copy.png -------------------------------------------------------------------------------- /cut.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ProgrammingHero1/BS_Word/0987e07f14ab5288ec6a9715cae36dae8a7387ae/cut.png -------------------------------------------------------------------------------- /italic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ProgrammingHero1/BS_Word/0987e07f14ab5288ec6a9715cae36dae8a7387ae/italic.png -------------------------------------------------------------------------------- /justification.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ProgrammingHero1/BS_Word/0987e07f14ab5288ec6a9715cae36dae8a7387ae/justification.png -------------------------------------------------------------------------------- /left-align.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ProgrammingHero1/BS_Word/0987e07f14ab5288ec6a9715cae36dae8a7387ae/left-align.png -------------------------------------------------------------------------------- /main.py: -------------------------------------------------------------------------------- 1 | import sys 2 | 3 | from PyQt5.QtWidgets import * 4 | from PyQt5.QtGui import * 5 | from PyQt5.QtPrintSupport import * 6 | 7 | 8 | class BSWord(QMainWindow): 9 | def __init__(self): 10 | super(BSWord, self).__init__() 11 | self.editor = QTextEdit() 12 | self.editor.setFontPointSize(20) 13 | self.setCentralWidget(self.editor) 14 | self.font_size_box = QSpinBox() 15 | self.showMaximized() 16 | self.setWindowTitle('My BS Word') 17 | self.create_tool_bar() 18 | self.create_menu_bar() 19 | 20 | def create_menu_bar(self): 21 | menu_bar = QMenuBar() 22 | 23 | file_menu = QMenu('File', self) 24 | menu_bar.addMenu(file_menu) 25 | 26 | save_as_pdf_action = QAction('save as pdf', self) 27 | save_as_pdf_action.triggered.connect(self.save_as_pdf) 28 | file_menu.addAction(save_as_pdf_action) 29 | 30 | edit_menu = QMenu('Edit', self) 31 | menu_bar.addMenu(edit_menu) 32 | 33 | view_menu = QMenu('View', self) 34 | menu_bar.addMenu(view_menu) 35 | 36 | self.setMenuBar(menu_bar) 37 | 38 | def create_tool_bar(self): 39 | tool_bar = QToolBar() 40 | 41 | undo_action = QAction(QIcon('undo.png'), 'undo', self) 42 | undo_action.triggered.connect(self.editor.undo) 43 | tool_bar.addAction(undo_action) 44 | 45 | redo_action = QAction(QIcon('redo.png'), 'redo', self) 46 | redo_action.triggered.connect(self.editor.redo) 47 | tool_bar.addAction(redo_action) 48 | 49 | tool_bar.addSeparator() 50 | tool_bar.addSeparator() 51 | 52 | cut_action = QAction(QIcon('cut.png'), 'cut', self) 53 | cut_action.triggered.connect(self.editor.cut) 54 | tool_bar.addAction(cut_action) 55 | 56 | copy_action = QAction(QIcon('copy.png'), 'copy', self) 57 | copy_action.triggered.connect(self.editor.copy) 58 | tool_bar.addAction(copy_action) 59 | 60 | paste_action = QAction(QIcon('paste.png'), 'paste', self) 61 | paste_action.triggered.connect(self.editor.paste) 62 | tool_bar.addAction(paste_action) 63 | 64 | tool_bar.addSeparator() 65 | tool_bar.addSeparator() 66 | 67 | self.font_size_box.setValue(20) 68 | self.font_size_box.valueChanged.connect(self.set_font_size) 69 | tool_bar.addWidget(self.font_size_box) 70 | 71 | self.addToolBar(tool_bar) 72 | 73 | def set_font_size(self): 74 | value = self.font_size_box.value() 75 | self.editor.setFontPointSize(value) 76 | 77 | def save_as_pdf(self): 78 | file_path, _ = QFileDialog.getSaveFileName(self, 'Export PDF', None, 'PDF Files (*.pdf)') 79 | printer = QPrinter(QPrinter.HighResolution) 80 | printer.setOutputFormat(QPrinter.PdfFormat) 81 | printer.setOutputFileName(file_path) 82 | self.editor.document().print_(printer) 83 | 84 | 85 | app = QApplication(sys.argv) 86 | window = BSWord() 87 | window.show() 88 | sys.exit(app.exec_()) -------------------------------------------------------------------------------- /main_complete.py: -------------------------------------------------------------------------------- 1 | """ Docx 2 | 3 | author: ashraf minhaj 4 | mail : ashraf_minhaj@yahoo.com 5 | """ 6 | 7 | """ 8 | install - 9 | $ pip install pyqt5 10 | $ pip install docx2txt 11 | """ 12 | 13 | import sys 14 | from PyQt5.QtGui import * 15 | from PyQt5.QtWidgets import * 16 | from PyQt5.QtCore import * 17 | from PyQt5.QtPrintSupport import * 18 | import docx2txt 19 | 20 | 21 | class MainApp(QMainWindow): 22 | """ the main class of our app """ 23 | def __init__(self): 24 | """ init things here """ 25 | super().__init__() # parent class initializer 26 | 27 | # window title 28 | self.title = "Google Doc Clone" 29 | self.setWindowTitle(self.title) 30 | 31 | # editor section 32 | self.editor = QTextEdit(self) 33 | self.setCentralWidget(self.editor) 34 | 35 | # create menubar and toolbar first 36 | self.create_menu_bar() 37 | self.create_toolbar() 38 | 39 | # after craeting toolabr we can call and select font size 40 | font = QFont('Times', 12) 41 | self.editor.setFont(font) 42 | self.editor.setFontPointSize(12) 43 | 44 | # stores path 45 | self.path = '' 46 | 47 | def create_menu_bar(self): 48 | menuBar = QMenuBar(self) 49 | 50 | """ add elements to the menubar """ 51 | # App icon will go here 52 | app_icon = menuBar.addMenu(QIcon("doc_icon.png"), "icon") 53 | 54 | # file menu ** 55 | file_menu = QMenu("File", self) 56 | menuBar.addMenu(file_menu) 57 | 58 | save_action = QAction('Save', self) 59 | save_action.triggered.connect(self.file_save) 60 | file_menu.addAction(save_action) 61 | 62 | open_action = QAction('Open', self) 63 | open_action.triggered.connect(self.file_open) 64 | file_menu.addAction(open_action) 65 | 66 | rename_action = QAction('Rename', self) 67 | rename_action.triggered.connect(self.file_saveas) 68 | file_menu.addAction(rename_action) 69 | 70 | pdf_action = QAction("Save as PDF", self) 71 | pdf_action.triggered.connect(self.save_pdf) 72 | file_menu.addAction(pdf_action) 73 | 74 | 75 | # edit menu ** 76 | edit_menu = QMenu("Edit", self) 77 | menuBar.addMenu(edit_menu) 78 | 79 | # paste 80 | paste_action = QAction('Paste', self) 81 | paste_action.triggered.connect(self.editor.paste) 82 | edit_menu.addAction(paste_action) 83 | 84 | # clear 85 | clear_action = QAction('Clear', self) 86 | clear_action.triggered.connect(self.editor.clear) 87 | edit_menu.addAction(clear_action) 88 | 89 | # select all 90 | select_action = QAction('Select All', self) 91 | select_action.triggered.connect(self.editor.selectAll) 92 | edit_menu.addAction(select_action) 93 | 94 | # view menu ** 95 | view_menu = QMenu("View", self) 96 | menuBar.addMenu(view_menu) 97 | 98 | # fullscreen 99 | fullscr_action = QAction('Full Screen View', self) 100 | fullscr_action.triggered.connect(lambda : self.showFullScreen()) 101 | view_menu.addAction(fullscr_action) 102 | 103 | # normal screen 104 | normscr_action = QAction('Normal View', self) 105 | normscr_action.triggered.connect(lambda : self.showNormal()) 106 | view_menu.addAction(normscr_action) 107 | 108 | # minimize 109 | minscr_action = QAction('Minimize', self) 110 | minscr_action.triggered.connect(lambda : self.showMinimized()) 111 | view_menu.addAction(minscr_action) 112 | 113 | self.setMenuBar(menuBar) 114 | 115 | def create_toolbar(self): 116 | # Using a title 117 | ToolBar = QToolBar("Tools", self) 118 | 119 | # undo 120 | undo_action = QAction(QIcon("undo.png"), 'Undo', self) 121 | undo_action.triggered.connect(self.editor.undo) 122 | ToolBar.addAction(undo_action) 123 | 124 | # redo 125 | redo_action = QAction(QIcon("redo.png"), 'Redo', self) 126 | redo_action.triggered.connect(self.editor.redo) 127 | ToolBar.addAction(redo_action) 128 | 129 | # adding separator 130 | ToolBar.addSeparator() 131 | 132 | # copy 133 | copy_action = QAction(QIcon("copy.png"), 'Copy', self) 134 | copy_action.triggered.connect(self.editor.copy) 135 | ToolBar.addAction(copy_action) 136 | 137 | # cut 138 | cut_action = QAction(QIcon("cut.png"), 'Cut', self) 139 | cut_action.triggered.connect(self.editor.cut) 140 | ToolBar.addAction(cut_action) 141 | 142 | # paste 143 | paste_action = QAction(QIcon("paste.png"), 'Paste', self) 144 | paste_action.triggered.connect(self.editor.paste) 145 | ToolBar.addAction(paste_action) 146 | 147 | # adding separator 148 | ToolBar.addSeparator() 149 | ToolBar.addSeparator() 150 | 151 | # fonts 152 | self.font_combo = QComboBox(self) 153 | self.font_combo.addItems(["Courier Std", "Hellentic Typewriter Regular", "Helvetica", "Arial", "SansSerif", "Helvetica", "Times", "Monospace"]) 154 | self.font_combo.activated.connect(self.set_font) # connect with function 155 | ToolBar.addWidget(self.font_combo) 156 | 157 | # font size 158 | self.font_size = QSpinBox(self) 159 | self.font_size.setValue(12) 160 | self.font_size.valueChanged.connect(self.set_font_size) # connect with funcion 161 | ToolBar.addWidget(self.font_size) 162 | 163 | # separator 164 | ToolBar.addSeparator() 165 | 166 | # bold 167 | bold_action = QAction(QIcon("bold.png"), 'Bold', self) 168 | bold_action.triggered.connect(self.bold_text) 169 | ToolBar.addAction(bold_action) 170 | 171 | # underline 172 | underline_action = QAction(QIcon("underline.png"), 'Underline', self) 173 | underline_action.triggered.connect(self.underline_text) 174 | ToolBar.addAction(underline_action) 175 | 176 | # italic 177 | italic_action = QAction(QIcon("italic.png"), 'Italic', self) 178 | italic_action.triggered.connect(self.italic_text) 179 | ToolBar.addAction(italic_action) 180 | 181 | # separator 182 | ToolBar.addSeparator() 183 | 184 | # text alignment 185 | right_alignment_action = QAction(QIcon("right-align.png"), 'Align Right', self) 186 | right_alignment_action.triggered.connect(lambda : self.editor.setAlignment(Qt.AlignRight)) 187 | ToolBar.addAction(right_alignment_action) 188 | 189 | left_alignment_action = QAction(QIcon("left-align.png"), 'Align Left', self) 190 | left_alignment_action.triggered.connect(lambda : self.editor.setAlignment(Qt.AlignLeft)) 191 | ToolBar.addAction(left_alignment_action) 192 | 193 | justification_action = QAction(QIcon("justification.png"), 'Center/Justify', self) 194 | justification_action.triggered.connect(lambda : self.editor.setAlignment(Qt.AlignCenter)) 195 | ToolBar.addAction(justification_action) 196 | 197 | # separator 198 | ToolBar.addSeparator() 199 | 200 | # zoom in 201 | zoom_in_action = QAction(QIcon("zoom-in.png"), 'Zoom in', self) 202 | zoom_in_action.triggered.connect(self.editor.zoomIn) 203 | ToolBar.addAction(zoom_in_action) 204 | 205 | # zoom out 206 | zoom_out_action = QAction(QIcon("zoom-out.png"), 'Zoom out', self) 207 | zoom_out_action.triggered.connect(self.editor.zoomOut) 208 | ToolBar.addAction(zoom_out_action) 209 | 210 | 211 | # separator 212 | ToolBar.addSeparator() 213 | 214 | self.addToolBar(ToolBar) 215 | 216 | def italic_text(self): 217 | # if already italic, change into normal, else italic 218 | state = self.editor.fontItalic() 219 | self.editor.setFontItalic(not(state)) 220 | 221 | def underline_text(self): 222 | # if already underlined, change into normal, else underlined 223 | state = self.editor.fontUnderline() 224 | self.editor.setFontUnderline(not(state)) 225 | 226 | def bold_text(self): 227 | # if already bold, make normal, else make bold 228 | if self.editor.fontWeight() != QFont.Bold: 229 | self.editor.setFontWeight(QFont.Bold) 230 | return 231 | self.editor.setFontWeight(QFont.Normal) 232 | 233 | def set_font(self): 234 | font = self.font_combo.currentText() 235 | self.editor.setCurrentFont(QFont(font)) 236 | 237 | def set_font_size(self): 238 | value = self.font_size.value() 239 | self.editor.setFontPointSize(value) 240 | 241 | # we can also make it one liner without writing such function. 242 | # by using lamba function - 243 | # self.font_size.valueChanged.connect(self.editor.setFontPointSize(self.font_size.value())) 244 | 245 | 246 | def file_open(self): 247 | self.path, _ = QFileDialog.getOpenFileName(self, "Open file", "", "Text documents (*.text);Text documents (*.txt);All files (*.*)") 248 | 249 | try: 250 | #with open(self.path, 'r') as f: 251 | # text = f.read() 252 | text = docx2txt.process(self.path) # docx2txt 253 | #doc = Document(self.path) # if using docx 254 | #text = '' 255 | #for line in doc.paragraphs: 256 | # text += line.text 257 | except Exception as e: 258 | print(e) 259 | else: 260 | self.editor.setText(text) 261 | self.update_title() 262 | 263 | def file_save(self): 264 | print(self.path) 265 | if self.path == '': 266 | # If we do not have a path, we need to use Save As. 267 | self.file_saveas() 268 | 269 | text = self.editor.toPlainText() 270 | 271 | try: 272 | with open(self.path, 'w') as f: 273 | f.write(text) 274 | self.update_title() 275 | except Exception as e: 276 | print(e) 277 | 278 | def file_saveas(self): 279 | self.path, _ = QFileDialog.getSaveFileName(self, "Save file", "", "text documents (*.text);Text documents (*.txt);All files (*.*)") 280 | 281 | if self.path == '': 282 | return # If dialog is cancelled, will return '' 283 | 284 | text = self.editor.toPlainText() 285 | 286 | try: 287 | with open(path, 'w') as f: 288 | f.write(text) 289 | self.update_title() 290 | except Exception as e: 291 | print(e) 292 | 293 | def update_title(self): 294 | self.setWindowTitle(self.title + ' ' + self.path) 295 | 296 | def save_pdf(self): 297 | f_name, _ = QFileDialog.getSaveFileName(self, "Export PDF", None, "PDF files (.pdf);;All files()") 298 | print(f_name) 299 | 300 | if f_name != '': # if name not empty 301 | printer = QPrinter(QPrinter.HighResolution) 302 | printer.setOutputFormat(QPrinter.PdfFormat) 303 | printer.setOutputFileName(f_name) 304 | self.editor.document().print_(printer) 305 | 306 | 307 | app = QApplication(sys.argv) 308 | window = MainApp() 309 | window.show() 310 | sys.exit(app.exec_()) -------------------------------------------------------------------------------- /paste.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ProgrammingHero1/BS_Word/0987e07f14ab5288ec6a9715cae36dae8a7387ae/paste.png -------------------------------------------------------------------------------- /printing.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ProgrammingHero1/BS_Word/0987e07f14ab5288ec6a9715cae36dae8a7387ae/printing.png -------------------------------------------------------------------------------- /redo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ProgrammingHero1/BS_Word/0987e07f14ab5288ec6a9715cae36dae8a7387ae/redo.png -------------------------------------------------------------------------------- /right-align.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ProgrammingHero1/BS_Word/0987e07f14ab5288ec6a9715cae36dae8a7387ae/right-align.png -------------------------------------------------------------------------------- /save.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ProgrammingHero1/BS_Word/0987e07f14ab5288ec6a9715cae36dae8a7387ae/save.png -------------------------------------------------------------------------------- /underline.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ProgrammingHero1/BS_Word/0987e07f14ab5288ec6a9715cae36dae8a7387ae/underline.png -------------------------------------------------------------------------------- /undo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ProgrammingHero1/BS_Word/0987e07f14ab5288ec6a9715cae36dae8a7387ae/undo.png -------------------------------------------------------------------------------- /zoom-in.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ProgrammingHero1/BS_Word/0987e07f14ab5288ec6a9715cae36dae8a7387ae/zoom-in.png -------------------------------------------------------------------------------- /zoom-out.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ProgrammingHero1/BS_Word/0987e07f14ab5288ec6a9715cae36dae8a7387ae/zoom-out.png --------------------------------------------------------------------------------