1 /*
2 	VeroRoute - Qt based Veroboard/Perfboard/PCB layout & routing application.
3 
4 	Copyright (C) 2017  Alex Lawrow    ( dralx@users.sourceforge.net )
5 
6 	This program is free software: you can redistribute it and/or modify
7 	it under the terms of the GNU General Public License as published by
8 	the Free Software Foundation, either version 3 of the License, or
9 	(at your option) any later version.
10 
11 	This program is distributed in the hope that it will be useful,
12 	but WITHOUT ANY WARRANTY; without even the implied warranty of
13 	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 	GNU General Public License for more details.
15 
16 	You should have received a copy of the GNU General Public License
17 	along with this program.  If not, see <http://www.gnu.org/licenses/>.
18 */
19 
20 #pragma once
21 
22 #include <QtGui>
23 #include <QApplication>
24 #include <QColorDialog>
25 #include <QDockWidget>
26 #include <QFileDialog>
27 #include <QLabel>
28 #include <QListWidgetItem>
29 #include <QMainWindow>
30 #include <QMessageBox>
31 #include <QNetworkAccessManager>
32 #include <QNetworkReply>
33 #include <QNetworkRequest>
34 #include <QWidget>
35 #include "HistoryManager.h"
36 #include "GWriter.h"
37 #include "myscrollarea.h"
38 
39 namespace Ui { class MainWindow; }
40 
41 class ControlDialog;
42 class TemplatesDialog;
43 class RenderingDialog;
44 class WireDialog;
45 class HotkeysDialog;
46 class InfoDialog;
47 class CompDialog;
48 class TextDialog;
49 class BomDialog;
50 class PinDialog;
51 class FindDialog;
52 
53 const size_t MAX_RECENT_FILES = 10;
54 
55 class MainWindow : public QMainWindow
56 {
57 	friend class ControlDialog;
58 	friend class TemplatesDialog;
59 	friend class RenderingDialog;
60 	friend class WireDialog;
61 	friend class HotkeysDialog;
62 	friend class InfoDialog;
63 	friend class CompDialog;
64 	friend class TextDialog;
65 	friend class BomDialog;
66 	friend class PinDialog;
67 	friend class FindDialog;
68 
69 	Q_OBJECT
70 
71 public:
72 	explicit MainWindow(const QString& localDataPathStr, const QString& tutorialsPathStr, QWidget* parent = nullptr);
73 	~MainWindow();
74 
75 	void ResetView(bool bTutorial = false);
76 	void CheckFolders();
77 	// Helper for mouse
78 	void GetPixMapXY(const QPoint& currentPoint, int& pixmapX, int& pixmapY) const;
79 	void GetRowCol(const QPoint& currentPoint, int& row, int& col, double& deltaRow, double& deltaCol) const;
80 	void GetRowCol(const QPoint& currentPoint, const int rows, const int cols, int& row, int& col, double& deltaRow, double& deltaCol) const;
81 
82 	// Helpers for rendering
83 	void GetFirstRowCol(int& iRow, int& iCol) const;
84 	void GetXY(const GuiControl& guiCtrl, double row, double col, int& X, int& Y) const;
85 	void GetLRTB(const GuiControl& guiCtrl, double percent, double row, double col, int& L, int& R, int& T, int& B) const;
86 	void GetLRTB(const GuiControl& guiCtrl, const Component& comp, int& L, int& R, int& T, int& B) const;
87 	void GetLRTB(const GuiControl& guiCtrl, const Rect& rect, int& L, int& R, int& T, int& B) const;
88 	void GetXY(const GuiControl& guiCtrl, const Component& comp, int& X, int& Y) const;
89 	void GetRulerExact(Board& board, const QPoint& p, QPointF& pOut) const;
90 
GetCtrlKeyDown()91 	const bool&	GetCtrlKeyDown() const	{ return m_bCtrlKeyDown;	}
GetShiftKeyDown()92 	const bool&	GetShiftKeyDown() const	{ return m_bShiftKeyDown;	}
GetPaintPins()93 	const bool&	GetPaintPins() const	{ return m_bPaintPins;		}
GetPaintBoard()94 	const bool&	GetPaintBoard() const	{ return m_bPaintBoard;		}
GetPaintFlood()95 	const bool&	GetPaintFlood() const	{ return m_bPaintFlood;		}
GetPaintLyrPref()96 	const bool&	GetPaintLyrPref() const	{ return m_bPaintLyrPref;	}
GetDefiningRect()97 	const bool&	GetDefiningRect() const	{ return m_bDefiningRect;	}
GetResizingText()98 	const bool&	GetResizingText() const	{ return m_bResizingText;	}
SetCtrlKeyDown(bool b)99 	void		SetCtrlKeyDown(bool b)	{ m_bCtrlKeyDown	= b; }
SetShiftKeyDown(bool b)100 	void		SetShiftKeyDown(bool b)	{ m_bShiftKeyDown	= b; }
101 	void		SetPaintPins(bool b);
102 	void		SetPaintBoard(bool b);
103 	void		SetPaintFlood(bool b);
104 	void		SetPaintLyrPref(bool b);
105 	void		SetDefiningRect(bool b);
SetResizingText(bool b)106 	void		SetResizingText(bool b)	{ m_bResizingText	= b; }
107 protected:
108 	void paintEvent(QPaintEvent* event);
109 	void wheelEvent(QWheelEvent* event);
110 	void mousePressEvent(QMouseEvent* event);
111 	void mouseDoubleClickEvent(QMouseEvent* event);
112 	void mouseMoveEvent(QMouseEvent* event);
113 	void mouseReleaseEvent(QMouseEvent* event);
114 	void keyPressEvent(QKeyEvent* event);
115 	void keyReleaseEvent(QKeyEvent* event);
116 	void commonKeyPressEvent(QKeyEvent* event);		// So child dialogs can relay Ctrl and Shift to the main window
117 	void commonKeyReleaseEvent(QKeyEvent* event);	// So child dialogs can relay Ctrl and Shift to the main window
118 	void specialKeyPressEvent(QKeyEvent* event);	// So child dialogs can do Ctrl+Q etc
119 	void dragEnterEvent(QDragEnterEvent *e);
120 	void dropEvent(QDropEvent *e);
121 public slots:
122 	void Startup();
123 	// File menu items
124 	void New();
125 	void Open();
126 	void OpenRecent();
127 	void Merge();
128 	void Save();
129 	void SaveAs();
130 	void ImportTango();
131 	void ImportOrcad();
132 	void WritePDF();
133 	void WritePNG();
134 	void WriteGerber(const bool& bTwoLayerGerber, const bool& bMetric);
WriteGerber1in()135 	void WriteGerber1in()	{ WriteGerber(false, false); }
WriteGerber1mm()136 	void WriteGerber1mm()	{ WriteGerber(false, true); }
WriteGerber2in()137 	void WriteGerber2in()	{ WriteGerber(true, false); }
WriteGerber2mm()138 	void WriteGerber2mm()	{ WriteGerber(true, true); }
139 	void ClearRecentFiles();
140 	void Quit();
141 	// View menu items
142 	void ZoomIn();
143 	void ZoomOut();
144 	void Crop();
145 	void ToggleGrid();
146 	void ToggleText();
147 	void ToggleFlipH();
148 	void ToggleFlipV();
149 	void TogglePinLabels();
150 	void ToggleFlyWires();
151 	void ToggleRuler();
152 	// Toolbar items
153 	void VeroV();
154 	void VeroH();
155 	void Fat();
156 	void Thin();
157 	void Curved();
158 	void ToggleDiagsMin();
159 	void ToggleDiagsMax();
160 	void ToggleFill();
161 	void ToggleSelectArea();
162 	// Edit menu items
163 	void Undo();
164 	void Redo();
165 	void Copy();
166 	void Group();
167 	void Ungroup();
168 	void SelectAll();
169 	void SelectAllInRects();
170 	void Delete();
171 	// Add menu items
AddMarker()172 	void AddMarker()			{ AddPart(COMP::MARK); }
AddPad()173 	void AddPad()				{ AddPart(COMP::PAD); }
AddPadFlyWire()174 	void AddPadFlyWire()		{ AddPart(COMP::PAD_FLYINGWIRE); }
AddWire()175 	void AddWire()				{ AddPart(COMP::WIRE); }
AddResistor()176 	void AddResistor()			{ AddPart(COMP::RESISTOR); }
AddInductor()177 	void AddInductor()			{ AddPart(COMP::INDUCTOR); }
AddCrystal()178 	void AddCrystal()			{ AddPart(COMP::CRYSTAL); }
AddDiode()179 	void AddDiode()				{ AddPart(COMP::DIODE); }
AddLED()180 	void AddLED()				{ AddPart(COMP::LED); }
AddCapCeramic()181 	void AddCapCeramic()		{ AddPart(COMP::CAP_CERAMIC); }
AddCapFilm()182 	void AddCapFilm()			{ AddPart(COMP::CAP_FILM); }
AddCapFilmWide()183 	void AddCapFilmWide()		{ AddPart(COMP::CAP_FILM_WIDE); }
AddCapElectro200NP()184 	void AddCapElectro200NP()	{ AddPart(COMP::CAP_ELECTRO_200_NP); }
AddCapElectro250NP()185 	void AddCapElectro250NP()	{ AddPart(COMP::CAP_ELECTRO_250_NP); }
AddCapElectro300NP()186 	void AddCapElectro300NP()	{ AddPart(COMP::CAP_ELECTRO_300_NP); }
AddCapElectro400NP()187 	void AddCapElectro400NP()	{ AddPart(COMP::CAP_ELECTRO_400_NP); }
AddCapElectro500NP()188 	void AddCapElectro500NP()	{ AddPart(COMP::CAP_ELECTRO_500_NP); }
AddCapElectro600NP()189 	void AddCapElectro600NP()	{ AddPart(COMP::CAP_ELECTRO_600_NP); }
AddCapElectro200()190 	void AddCapElectro200()		{ AddPart(COMP::CAP_ELECTRO_200); }
AddCapElectro250()191 	void AddCapElectro250()		{ AddPart(COMP::CAP_ELECTRO_250); }
AddCapElectro300()192 	void AddCapElectro300()		{ AddPart(COMP::CAP_ELECTRO_300); }
AddCapElectro400()193 	void AddCapElectro400()		{ AddPart(COMP::CAP_ELECTRO_400); }
AddCapElectro500()194 	void AddCapElectro500()		{ AddPart(COMP::CAP_ELECTRO_500); }
AddCapElectro600()195 	void AddCapElectro600()		{ AddPart(COMP::CAP_ELECTRO_600); }
AddTO92()196 	void AddTO92()				{ AddPart(COMP::TO92); }
AddTO18()197 	void AddTO18()				{ AddPart(COMP::TO18); }
AddTO39()198 	void AddTO39()				{ AddPart(COMP::TO39); }
AddTO220()199 	void AddTO220()				{ AddPart(COMP::TO220); }
AddTrimVert()200 	void AddTrimVert()			{ AddPart(COMP::TRIM_VERT); }
AddTrimVertOffset()201 	void AddTrimVertOffset()	{ AddPart(COMP::TRIM_VERT_OFFSET); }
AddTrimVertOffsetWide()202 	void AddTrimVertOffsetWide(){ AddPart(COMP::TRIM_VERT_OFFSET_WIDE); }
AddTrimFlat()203 	void AddTrimFlat()			{ AddPart(COMP::TRIM_FLAT); }
AddTrimFlatWide()204 	void AddTrimFlatWide()		{ AddPart(COMP::TRIM_FLAT_WIDE); }
AddSIP()205 	void AddSIP()				{ AddPart(COMP::SIP); }
AddDIP()206 	void AddDIP()				{ AddPart(COMP::DIP); }
AddStrip100()207 	void AddStrip100()			{ AddPart(COMP::STRIP_100); }
AddBlock100()208 	void AddBlock100()			{ AddPart(COMP::BLOCK_100); }
AddBlock200()209 	void AddBlock200()			{ AddPart(COMP::BLOCK_200); }
AddSwitchST()210 	void AddSwitchST()			{ AddPart(COMP::SWITCH_ST); }
AddSwitchDT()211 	void AddSwitchDT()			{ AddPart(COMP::SWITCH_DT); }
AddSwitchST_DIP()212 	void AddSwitchST_DIP()		{ AddPart(COMP::SWITCH_ST_DIP); }
AddVeroNumbers()213 	void AddVeroNumbers()		{ AddPart(COMP::VERO_NUMBER); }
AddVeroLetters()214 	void AddVeroLetters()		{ AddPart(COMP::VERO_LETTER); }
AddTextBox()215 	void AddTextBox()
216 	{
217 		SetCurrentTextId(BAD_TEXTID);
218 		int iRow, iCol;
219 		GetFirstRowCol(iRow, iCol);
220 		m_board.AddTextBox(iRow, iCol);
221 		UpdateHistory("Add text");
222 		UpdateControls();
223 		RepaintSkipRouting();
224 		ShowTextDialog();
225 	}
226 	// Windows menu items
227 	void ShowControlDialog();
228 	void ShowTemplatesDialog();
229 	void ShowRenderingDialog();
230 	void ShowWireDialog();
231 	void ShowHotkeysDialog();
232 	void ShowInfoDialog();
233 	void ShowCompDialog();
234 	void ShowTextDialog();
235 	void ShowBomDialog();
236 	void ShowPinDialog();
237 	void ShowFindDialog();
238 	void ShowAbout();
239 	void ShowSupport();
240 	// Layers menu items
241 	void AddLayer();
242 	void RemoveLayer();
243 	void SwitchLayer();
244 	void ToggleVias();
245 	// Help menu items
246 	void LoadFirstTutorial();
247 	void LoadPrevTutorial();
248 	void LoadNextTutorial();
249 	void LoadTutorial();		// Helper
250 	// Check version against Sourceforge
251 	void UpdateCheck();
252 	void HandleNetworkReply(QNetworkReply* reply);
253 
254 	// Helpers for child dialogs
255 	void ShowDlg(QWidget* p);
256 
257 	// View controls
258 	void TrackSliderChanged(int i);
259 	void SaturationSliderChanged(int i);
260 	void CompSliderChanged(int i);
261 	void FillSliderChanged(int i);
262 	void MarginChanged(int i);
263 	void SetShowGrid(bool b);
264 	void SetShowText(bool b);
265 	void SetFlipH(bool b);
266 	void SetFlipV(bool b);
267 	void SetShowPinLabels(bool b);
268 	void SetShowFlyWires(bool b);
269 	void SetFill(bool b);
270 	// Part controls
271 	void SetCompName(const QString& str);
272 	void SetCompValue(const QString& str);
273 	void SetCompType(const QString& str);
274 	void SetCompCustomFlag(const bool& b);
275 	void SetCompPadWidth(const int& i);
276 	void SetCompHoleWidth(const int& i);
CompRotateCCW()277 	void CompRotateCCW()	{ CompRotate(false); }
CompRotateCW()278 	void CompRotateCW()		{ CompRotate(true); }
CompGrow()279 	void CompGrow()			{ CompStretch(true); }
CompShrink()280 	void CompShrink()		{ CompStretch(false); }
CompGrow2()281 	void CompGrow2()		{ CompStretchWidth(true); }
CompShrink2()282 	void CompShrink2()		{ CompStretchWidth(false); }
CompTextCentre()283 	void CompTextCentre()	{ CompTextMove(0,  0); }
CompTextL()284 	void CompTextL()		{ CompTextMove(0, -1); }
CompTextR()285 	void CompTextR()		{ CompTextMove(0,  1); }
CompTextT()286 	void CompTextT()		{ CompTextMove(-1, 0); }
CompTextB()287 	void CompTextB()		{ CompTextMove( 1, 0); }
288 	// Bad Nodes lists
289 	void SetNodeId(QListWidgetItem* item);
290 	void ListNodes(bool bRebuild = true);
291 	// Routing controls
292 	void EnableRouting(bool b);
293 	void EnableFastRouting(bool b);
294 	void Paste();
295 	void Tidy();
296 	void WipeTracks();
297 	// Node color
298 	void AutoColor(bool b);
299 	void SelectNodeColor();
300 	// Track controls
301 	void SetTracksVeroV(bool b);
302 	void SetTracksVeroH(bool b);
303 	void SetTracksFat(bool b);
304 	void SetTracksThin(bool b);
305 	void SetTracksCurved(bool b);
306 	void SetDiagonalsOff(bool b);
307 	void SetDiagonalsMin(bool b);
308 	void SetDiagonalsMax(bool b);
309 	// Rendering options
310 	void SetBrightness(int i);
311 	void SetTrackWidth(int i);
312 	void SetHoleWidth(int i);
313 	void SetPadWidth(int i);
314 	void SetGapWidth(int i);
315 	void SetMaskWidth(int i);
316 	void SetSilkWidth(int i);
317 	void SetEdgeWidth(int i);
318 	void SetViaPadWidth(int i);
319 	void SetViaHoleWidth(int i);
320 	void SetTextSizeComp(int i);
321 	void SetTextSizePins(int i);
322 	void SetTargetRows(int i);
323 	void SetTargetCols(int i);
324 	void SetShowTarget(bool b);
325 	void SetShowCloseTracks(bool b);
326 	void SetAntialiasOff(bool b);
327 	void SetAntialiasOn(bool b);
328 	// Find parts by name/value
329 	void Find(bool bUseName, bool bExact, const QString& str);
330 	// Wire options
331 	void SetWireShare(bool b);
332 	void SetWireCross(bool b);
333 	// For text box dialog
334 	void SizeChanged(int i);
335 	void ToggleBold();
336 	void ToggleItalic();
337 	void ToggleUnderline();
338 	void AlignL();
339 	void AlignC();
340 	void AlignR();
341 	void AlignJ();
342 	void AlignTop();
343 	void AlignMid();
344 	void AlignBot();
345 	void SetText(const QString&);
346 	void ChooseTextColor();
347 	// For component editor dialog
GetCompDefiner()348 	CompDefiner& GetCompDefiner() { return m_board.GetCompDefiner(); }
349 	// For template dialog
GetTemplateManager()350 	TemplateManager& GetTemplateManager() { return m_templateMgr; }
351 	// Info dialog
SetInfoStr(const QString & str)352 	void SetInfoStr(const QString& str)	{ m_board.SetInfoStr(str.toStdString()); }
353 	void OpenVrt(const QString& fileName, bool bMerge = false);	// Helper for opening a vrt using Open(), Merge(), dropEvent(), or the command line
354 	// Component editor
355 	void DefinerSetValueStr(const QString& str);
356 	void DefinerSetPrefixStr(const QString& str);
357 	void DefinerSetTypeStr(const QString& str);
358 	void DefinerSetImportStr(const QString& str);
359 	void DefinerWidthChanged(int i);
360 	void DefinerHeightChanged(int i);
361 	void DefinerPadWidthChanged(int i);
362 	void DefinerHoleWidthChanged(int i);
363 	void DefinerSetPinShapeType(const QString& str);
364 	void DefinerToggledPinLabels(bool b);
365 	void DefinerToggledCustomFlag(bool b);
366 	void DefinerToggleShapeLine(bool b);
367 	void DefinerToggleShapeFill(bool b);
368 	void DefinerSetPinNumber(int i);
369 	void DefinerIncPinNumber(bool b);
370 	void DefinerSetShapeType(const QString& str);
371 	void DefinerSetCX(double d);
372 	void DefinerSetCY(double d);
373 	void DefinerSetDX(double d);
374 	void DefinerSetDY(double d);
375 	void DefinerSetA1(double d);
376 	void DefinerSetA2(double d);
377 	void DefinerSetA3(double d);
378 	void DefinerBuild();
379 	void DefinerToggleEditor();
380 	void DefinerAddLine();
381 	void DefinerAddRect();
382 	void DefinerAddRoundedRect();
383 	void DefinerAddEllipse();
384 	void DefinerAddArc();
385 	void DefinerAddChord();
386 	void DefinerChooseColor();
387 	void DefinerRaise();
388 	void DefinerLower();
389 private:
390 	void DestroyPixmapCache();
391 	void CreatePixmapCache(const GuiControl& guiCtrl, ColorManager& colorManager);
392 	void PaintViaGrey(const GuiControl& guiCtrl, QPainter& painter, const QPointF& pC);
393 	void PaintPadGrey(const GuiControl& guiCtrl, QPainter& painter, QPen& pen, const QPointF& pC, const int& iPadWidthMIL = 0);
394 	void PaintVia(const GuiControl& guiCtrl, QPainter& painter,  const QColor& color, const QPointF& pC, const bool& bGap = false);	// Helper
395 	void PaintPad(const GuiControl& guiCtrl, QPainter& painter,  const QColor& color, const QPointF& pC, const int& iPadWidthMIL = 0, const int& iHoleWidth_MIL = 0, const bool& bGap = false);	// Helper
396 	void PaintTag(const GuiControl& guiCtrl, QPainter& painter, const QColor& color, const QPointF& pC, const int& iPadWidthMIL, const int& iNbr, const int& iLyr);
397 	void PaintDiag(const GuiControl& guiCtrl, QPainter& painter, const QColor& color, const QPointF& pCorner, bool bLT);
398 	void PaintBlob(const GuiControl& guiCtrl, QPainter& painter, const QColor& color, const QPointF& pC, const QPointF& pCoffset, const int& iPerimeterCode, const bool bHavePad = false, const bool bGap = false);	// Helper
399 	void PaintBoard();
400 	void PaintCompDefiner();
401 	void HandleRouting();
402 	void RepaintWithListNodes(bool bNow = false);
403 	void RepaintWithRouting(bool bNow = false);
404 	void RepaintSkipRouting(bool bNow = false);
405 	void ShowCurrentRectSize();	// Show current rect size in status bar
GetCurrentLayer()406 	int	 GetCurrentLayer() const			{ return m_board.GetCurrentLayer(); }
GetCurrentNodeId()407 	int	 GetCurrentNodeId() const			{ return m_board.GetCurrentNodeId(); }
GetCurrentCompId()408 	int  GetCurrentCompId() const			{ return m_board.GetCurrentCompId(); }
GetCurrentTextId()409 	int  GetCurrentTextId() const			{ return m_board.GetCurrentTextId(); }
GetCurrentPinId()410 	int  GetCurrentPinId() const			{ return m_board.GetCurrentPinId(); }
GetCurrentShapeId()411 	int  GetCurrentShapeId() const			{ return m_board.GetCurrentShapeId(); }
SetCurrentNodeId(const int & i)412 	void SetCurrentNodeId(const int& i)		{ m_board.SetCurrentNodeId(i);	ListNodes(false); }
SetCurrentCompId(const int & i)413 	void SetCurrentCompId(const int& i)		{ m_board.SetCurrentCompId(i);	UpdateControls(); }
SetCurrentTextId(const int & i)414 	void SetCurrentTextId(const int& i)		{ m_board.SetCurrentTextId(i);	UpdateControls(); }
SetCurrentPinId(const int & i)415 	void SetCurrentPinId(const int& i)		{ m_board.SetCurrentPinId(i);	UpdateCompDialog(); }
SetCurrentShapeId(const int & i)416 	void SetCurrentShapeId(const int& i)	{ m_board.SetCurrentShapeId(i);	UpdateCompDialog(); }
GetCurrentTextRect()417 	TextRect& GetCurrentTextRect()			{ return m_board.GetTextMgr().GetTextRectById( GetCurrentTextId() ); }
418 	// Helpers for slots
419 	void ZoomHelper(int delta);
AddPart(COMP eType)420 	void AddPart(COMP eType)
421 	{
422 		if ( m_board.GetCompEdit() ) return;	// Do nothing in component editor mode
423 
424 		int iRow, iCol;
425 		GetFirstRowCol(iRow, iCol);
426 		const int compId = m_board.CreateComponent(iRow, iCol, eType);
427 		if ( compId == BAD_COMPID ) return;	// Reached component limit
428 
429 		GroupManager& groupMgr = m_board.GetGroupMgr();
430 		groupMgr.ResetUserGroup( compId );	// Reset the user group with the current comp (and its siblings)
431 		SetCurrentCompId(compId);
432 
433 		UpdateHistory("Add part"); UpdateControls(); UpdateBOM(); RepaintSkipRouting();
434 	}
AddFromTemplate(const Component & compTemp)435 	void AddFromTemplate(const Component& compTemp)
436 	{
437 		if ( m_board.GetCompEdit() ) return;	// Do nothing in component editor mode
438 
439 		int iRow, iCol;
440 		GetFirstRowCol(iRow, iCol);
441 		const int compId = m_board.CreateComponent(iRow, iCol, compTemp.GetType(), &compTemp);
442 		if ( compId == BAD_COMPID ) return;	// Reached component limit
443 
444 		GroupManager& groupMgr = m_board.GetGroupMgr();
445 		groupMgr.ResetUserGroup( compId );	// Reset the user group with the current comp (and its siblings)
446 		SetCurrentCompId(compId);
447 
448 		UpdateHistory("Add part"); UpdateControls(); UpdateBOM(); RepaintSkipRouting();
449 	}
450 	void CompRotate(const bool& bCW);
451 	void CompStretch(const bool& bGrow);
452 	void CompStretchWidth(const bool& bGrow);
453 	void CompTextMove(const int& deltaRow, const int& deltaCol);
454 
455 	// GUI update
456 	void UpdateRecentFiles(const QString* pFileName, bool bAdd);
457 	void UpdateWindowTitle();
458 	void UpdateRulerInfo();
459 	void UpdateControls();
460 	void UpdateCompDialog();
461 	void EnableCompDialogControls();
462 	void UpdateBOM();
463 	void UpdateTemplatesDialog();
464 	void UpdateTextDialog(bool bFull = false);
465 
466 	// Helpers
467 	void SetQuality(QPainter& p);
468 	void ResetRuler();
469 	bool CanModifyRuler() const;
470 	bool CanZoomIn() const;
471 	bool CanZoomOut() const;
472 	bool GetIsModified() const;
473 	bool GetMatchesVrtFile(const std::string& fileName) const;
474 	void ResetHistory(const std::string& str);
475 	void UpdateHistory(const std::string& str, const int compId = BAD_COMPID);
476 	void UpdateUndoRedoControls();
477 
478 	// Helper to auto-append suffix when writing a file
479 	QString GetSaveFileName(const QString& caption, const QString& nameFilter, const QString& defaultSuffix);
480 
481 	QColor	GetBackgroundColor() const;	// For screen only.  PDF is always white.
482 
483 	// Pens
484 	QPen	m_rulerPen;
485 	QPen	m_backgroundPen;
486 	QPen	m_darkGreyPen;
487 	QPen	m_blackPen;
488 	QPen	m_whitePen;
489 	QPen	m_redPen;
490 	QPen	m_orangePen;
491 	QPen	m_lightBluePen;
492 	QPen	m_varPen;
493 	QPen	m_dotPen;
494 	QPen	m_dashPen;
495 	QBrush	m_backgroundBrush;
496 	QBrush	m_darkBrush;
497 	QBrush	m_varBrush;
498 private:
499 	QNetworkAccessManager	m_networkMgr;	// For checking version against Sourceforge
500 	QAction*				m_recentFileAction[MAX_RECENT_FILES];
501 	QAction*				m_separator			= nullptr;	// At the end of the recent files list
502 	Ui::MainWindow*			ui					= nullptr;
503 	MyScrollArea*			m_scrollArea		= nullptr;	// The mainwindow contains a scrollable area ...
504 	QLabel*					m_label				= nullptr;	// ... for a QLabel widget that ...
505 	QPixmap					m_mainPixmap;					// ... contains a pixmap image of the whole board
506 	QLabel*					m_labelStatus		= nullptr;	// For permanent status bar text
507 	QDockWidget*			m_dockControlDlg	= nullptr;
508 	QDockWidget*			m_dockCompDlg		= nullptr;
509 	ControlDialog*			m_controlDlg		= nullptr;
510 	RenderingDialog*		m_renderingDlg		= nullptr;
511 	WireDialog*				m_wireDlg			= nullptr;
512 	HotkeysDialog*			m_hotkeysDlg		= nullptr;
513 	InfoDialog*				m_infoDlg			= nullptr;
514 	CompDialog*				m_compDlg			= nullptr;
515 	TextDialog*				m_textDlg			= nullptr;
516 	BomDialog*				m_bomDlg			= nullptr;
517 	TemplatesDialog*		m_templatesDlg		= nullptr;
518 	PinDialog*				m_pinDlg			= nullptr;
519 	FindDialog*				m_findDlg			= nullptr;
520 
521 	Board					m_board;			// *** The main object ***
522 	HistoryManager			m_historyMgr;		// Class to manage undo/redo
523 	TemplateManager			m_templateMgr;		// For component templates
524 	GWriter					m_gWriter;			// Writes Gerber files
525 	QString					m_fileName;			// The loaded/saved .vrt file
526 	QString					m_pdfFileName;		// The saved PDF file
527 	QString					m_gerberFileName;	// The saved Gerber file
528 	std::string				m_mouseActionString;// For the undo/redo history
529 	std::string				m_localDataPathStr;	// The path to the "history" and "templates" folders
530 	std::string				m_tutorialsPathStr;	// The path to the "tutorials" folder and "veroroute.png"
531 
532 	// Cached pixmaps containing pre-colored pads and blobs.
533 	QPixmap**	m_ppPixmapPad		= nullptr;	// A pad in the host element
534 	QPixmap**	m_ppPixmapVia		= nullptr;	// A via in the host element
535 	QPixmap**	m_ppPixmapDiag		= nullptr;	// For filling small diagonal gaps not covered by blob pixmaps
536 	QPixmap**	m_ppPixmapBlob		= nullptr;	// A composite shape with all the host element connections
537 	QPixmap*	m_pPixmapDiagLT		= nullptr;	// Used instead of m_ppPixmapDiag for custom colors
538 	QPixmap*	m_pPixmapDiagRT		= nullptr;	// Used instead of m_ppPixmapDiag for custom colors
539 	int			m_radPixmapPad		= 0;		// Half pixmap width ...
540 	int			m_radPixmapVia		= 0;		// ...
541 	int			m_radPixmapDiag		= 0;		// ...
542 	int			m_radPixmapBlob		= 0;		// ...
543 	QPoint		m_mousePos;
544 	bool		m_bRepaint			= false;	// Flag to make paintEvent() do something useful
545 	bool		m_bMouseClick		= false;	// Flag of click beginning
546 	bool		m_bLeftClick		= false;
547 	bool		m_bRightClick		= false;
548 	bool		m_bCtrlKeyDown		= false;
549 	bool		m_bShiftKeyDown		= false;
550 	bool		m_bPaintPins		= false;	// true ==> allow paint the component pins (and the board)
551 	bool		m_bPaintBoard		= false;	// true ==> allow paint the board only (not the component pins)
552 	bool		m_bPaintFlood		= false;	// true ==> allow flood-fill all connected tracks & pins
553 	bool		m_bPaintLyrPref		= false;	// true ==> allow paint layer preference to pins
554 	bool		m_bDefiningRect		= false;	// true ==> user is defining a rectangle
555 	bool		m_bResizingText		= false;	// true ==> user is resizing a text rectangle
556 	bool		m_bWritePDF			= false;	// true ==> draw to PDF file instead of screen
557 	bool		m_bWriteGerber		= false;	// true ==> draw to Gerber file instead of screen
558 	bool		m_bTwoLayerGerber	= false;	// true ==> 2-layer Gerber output instead of 1-layer
559 	bool		m_bHistoryDir		= false;	// true ==> have "history" folder
560 	bool		m_bTemplatesDir		= false;	// true ==> have "templates" folder
561 	bool		m_bRuler			= false;
562 	bool		m_bModifyRulerA		= false;
563 	int			m_XGRIDOFFSET		= 0;		// So we can centre when writing to PDF
564 	int			m_YGRIDOFFSET		= 0;		// So we can centre when writing to PDF
565 	int			m_XCORRECTION		= 0;		// So we can fully render pads larger than 100 mil diameter
566 	int			m_YCORRECTION		= 0;		// So we can fully render pads larger than 100 mil diameter
567 	int			m_gridRow			= 0;		// Board row corresponding to mouse position
568 	int			m_gridCol			= 0;		// Board col correspondong to mouse position
569 	QPoint		m_rulerA;
570 	QPoint		m_rulerB;
571 	int			m_iTutorialNumber	= -1;		// Tutorial file number 0,1,2,... (or -1 if not in tutorial mode)
572 };
573