[fritzing] Update to 0.8.3b.

Ed Marshall logic at fedoraproject.org
Sun Aug 11 06:06:37 UTC 2013


commit bd9d37d0e7c9753dc0f5fdbcc8ea863ca8030d72
Author: Ed Marshall <esm at logic.net>
Date:   Sat Aug 10 23:06:17 2013 -0700

    Update to 0.8.3b.

 fritzing-disable-autoupdate.patch | 8410 ++++++++++++++++++++++++++++++++++++-
 fritzing-use-external-libs.patch  |  403 --
 fritzing.spec                     |    7 +-
 sources                           |    3 +-
 4 files changed, 8279 insertions(+), 544 deletions(-)
---
diff --git a/fritzing-disable-autoupdate.patch b/fritzing-disable-autoupdate.patch
index e06669b..50fd26c 100644
--- a/fritzing-disable-autoupdate.patch
+++ b/fritzing-disable-autoupdate.patch
@@ -1,137 +1,144 @@
-diff -urN fritzing-0.7.12b.source.orig/src/fapplication.cpp fritzing-0.7.12b.source/src/fapplication.cpp
---- fritzing-0.7.12b.source.orig/src/fapplication.cpp	2013-02-25 05:02:58.000000000 -0800
-+++ fritzing-0.7.12b.source/src/fapplication.cpp	2013-02-25 18:30:14.337450882 -0800
-@@ -288,7 +288,6 @@
- 	m_mousePressed = false;
- 	m_referenceModel = NULL;
- 	m_started = false;
--	m_updateDialog = NULL;
- 	m_lastTopmostWindow = NULL;
- 	m_serviceType = NoService;
- 	m_splash = NULL;
-@@ -460,7 +459,6 @@
- 	}
- 
- 	m_started = false;
--	m_updateDialog = NULL;
- 	m_lastTopmostWindow = NULL;
- 
- 	connect(&m_activationTimer, SIGNAL(timeout()), this, SLOT(updateActivation()));
-@@ -516,10 +514,6 @@
- 		
- 	clearModels();
- 
--	if (m_updateDialog) {
--		delete m_updateDialog;
--	}
--
- 	FSvgRenderer::cleanup();
- 	ViewLayer::cleanup();
- 	ViewLayer::cleanup();
-@@ -1037,10 +1031,6 @@
- 	if (m_progressIndex >= 0) splash.showProgress(m_progressIndex, 0.825);
- 	ProcessEventBlocker::processEvents();
- 
--	m_updateDialog = new UpdateDialog();
--	connect(m_updateDialog, SIGNAL(enableAgainSignal(bool)), this, SLOT(enableCheckUpdates(bool)));
--	checkForUpdates(false);
--
- 	if (m_progressIndex >= 0) splash.showProgress(m_progressIndex, 0.875);
- 
- 	DebugDialog::debug("load something");
-@@ -1223,59 +1213,6 @@
-         ViewLayer::ViewLayerID viewLayerID;
- };
- 
--
--
--void FApplication::checkForUpdates() {
--	checkForUpdates(true);
--}
--
--void FApplication::checkForUpdates(bool atUserRequest)
--{
--	if (atUserRequest) {
--		enableCheckUpdates(false);
--	}
--
--	VersionChecker * versionChecker = new VersionChecker();
--
--	QSettings settings;
--	if (!atUserRequest) {
--		// if I've already been notified about these updates, don't bug me again
--		QString lastMainVersionChecked = settings.value("lastMainVersionChecked").toString();
--		if (!lastMainVersionChecked.isEmpty()) {
--			versionChecker->ignore(lastMainVersionChecked, false);
--		}
--		QString lastInterimVersionChecked = settings.value("lastInterimVersionChecked").toString();
--		if (!lastInterimVersionChecked.isEmpty()) {
--			versionChecker->ignore(lastInterimVersionChecked, true);
--		}
--	}
--
--    QString atom = QString("http://fritzing.org/download/feed/atom/%1/%2")
--		.arg(PLATFORM_NAME)
--		.arg(Version::makeRequestParamsString());
--    DebugDialog::debug(atom);
--    versionChecker->setUrl(atom);
--	m_updateDialog->setAtUserRequest(atUserRequest);
--	m_updateDialog->setVersionChecker(versionChecker);
--
--	if (atUserRequest) {
--		m_updateDialog->show();
--	}
--}
--
--void FApplication::enableCheckUpdates(bool enabled)
--{
--	//DebugDialog::debug("before enable check updates");
--    foreach (QWidget *widget, QApplication::topLevelWidgets()) {
--        MainWindow *mainWindow = qobject_cast<MainWindow *>(widget);
--		if (mainWindow) {
--			mainWindow->enableCheckUpdates(enabled);
--		}
--	}
--	//DebugDialog::debug("after enable check updates");
--}
--
--
- void FApplication::createUserDataStoreFolderStructure() {
- 	// make sure that the folder structure for parts and bins, exists
- 	QString userDataStorePath = FolderUtils::getUserDataStorePath();
-diff -urN fritzing-0.7.12b.source.orig/src/fapplication.h fritzing-0.7.12b.source/src/fapplication.h
---- fritzing-0.7.12b.source.orig/src/fapplication.h	2013-02-25 05:02:59.000000000 -0800
-+++ fritzing-0.7.12b.source/src/fapplication.h	2013-02-25 18:29:22.841458898 -0800
+diff -urN fritzing-0.8.3b.source.orig/src/fapplication.cpp fritzing-0.8.3b.source/src/fapplication.cpp
+--- fritzing-0.8.3b.source.orig/src/fapplication.cpp	2013-07-27 14:03:38.000000000 -0700
++++ fritzing-0.8.3b.source/src/fapplication.cpp	2013-08-10 22:52:45.541364980 -0700
+@@ -34,7 +34,6 @@
+ #include "help/helper.h"
+ #include "fsvgrenderer.h"
+ #include "version/versionchecker.h"
+-#include "version/updatedialog.h"
+ #include "itemdrag.h"
+ #include "dock/viewswitcher.h"
+ #include "items/wire.h"
+@@ -289,7 +288,6 @@
+ 	m_mousePressed = false;
+ 	m_referenceModel = NULL;
+ 	m_started = false;
+-	m_updateDialog = NULL;
+ 	m_lastTopmostWindow = NULL;
+ 	m_serviceType = NoService;
+ 	m_splash = NULL;
+@@ -468,7 +466,6 @@
+ 	}
+ 
+ 	m_started = false;
+-	m_updateDialog = NULL;
+ 	m_lastTopmostWindow = NULL;
+ 
+ 	connect(&m_activationTimer, SIGNAL(timeout()), this, SLOT(updateActivation()));
+@@ -524,10 +521,6 @@
+ 		
+ 	clearModels();
+ 
+-	if (m_updateDialog) {
+-		delete m_updateDialog;
+-	}
+-
+ 	FSvgRenderer::cleanup();
+ 	ViewLayer::cleanup();
+ 	ViewLayer::cleanup();
+@@ -1115,10 +1108,6 @@
+ 	if (m_progressIndex >= 0) splash.showProgress(m_progressIndex, 0.825);
+ 	ProcessEventBlocker::processEvents();
+ 
+-	m_updateDialog = new UpdateDialog();
+-	connect(m_updateDialog, SIGNAL(enableAgainSignal(bool)), this, SLOT(enableCheckUpdates(bool)));
+-	checkForUpdates(false);
+-
+ 	if (m_progressIndex >= 0) splash.showProgress(m_progressIndex, 0.875);
+ 
+ 	DebugDialog::debug("load something");
+@@ -1302,58 +1291,6 @@
+ };
+ 
+ 
+-
+-void FApplication::checkForUpdates() {
+-	checkForUpdates(true);
+-}
+-
+-void FApplication::checkForUpdates(bool atUserRequest)
+-{
+-	if (atUserRequest) {
+-		enableCheckUpdates(false);
+-	}
+-
+-	VersionChecker * versionChecker = new VersionChecker();
+-
+-	QSettings settings;
+-	if (!atUserRequest) {
+-		// if I've already been notified about these updates, don't bug me again
+-		QString lastMainVersionChecked = settings.value("lastMainVersionChecked").toString();
+-		if (!lastMainVersionChecked.isEmpty()) {
+-			versionChecker->ignore(lastMainVersionChecked, false);
+-		}
+-		QString lastInterimVersionChecked = settings.value("lastInterimVersionChecked").toString();
+-		if (!lastInterimVersionChecked.isEmpty()) {
+-			versionChecker->ignore(lastInterimVersionChecked, true);
+-		}
+-	}
+-
+-    QString atom = QString("http://fritzing.org/download/feed/atom/%1/%2")
+-		.arg(PLATFORM_NAME)
+-		.arg(Version::makeRequestParamsString(true));
+-    DebugDialog::debug(atom);
+-    versionChecker->setUrl(atom);
+-	m_updateDialog->setAtUserRequest(atUserRequest);
+-	m_updateDialog->setVersionChecker(versionChecker);
+-
+-	if (atUserRequest) {
+-		m_updateDialog->show();
+-	}
+-}
+-
+-void FApplication::enableCheckUpdates(bool enabled)
+-{
+-	//DebugDialog::debug("before enable check updates");
+-    foreach (QWidget *widget, QApplication::topLevelWidgets()) {
+-        MainWindow *mainWindow = qobject_cast<MainWindow *>(widget);
+-		if (mainWindow) {
+-			mainWindow->enableCheckUpdates(enabled);
+-		}
+-	}
+-	//DebugDialog::debug("after enable check updates");
+-}
+-
+-
+ void FApplication::createUserDataStoreFolderStructure() {
+ 	// make sure that the folder structure for parts and bins, exists
+ 	QString userDataStorePath = FolderUtils::getUserDataStorePath();
+diff -urN fritzing-0.8.3b.source.orig/src/fapplication.h fritzing-0.8.3b.source/src/fapplication.h
+--- fritzing-0.8.3b.source.orig/src/fapplication.h	2013-07-27 14:03:38.000000000 -0700
++++ fritzing-0.8.3b.source/src/fapplication.h	2013-08-10 22:50:50.837249496 -0700
 @@ -108,9 +108,6 @@
- public slots:
- 	void preferences();
- 	void preferencesAfter();
--	void checkForUpdates();
--	void checkForUpdates(bool atUserRequest);
--	void enableCheckUpdates(bool enabled);
- 	void createUserDataStoreFolderStructure();
- 	void changeActivation(bool activate, QWidget * originator);
- 	void updateActivation();
-@@ -180,7 +177,6 @@
- 	QStringList m_filesToLoad;
- 	QString m_libPath;
- 	QString m_translationPath;
--	class UpdateDialog * m_updateDialog;
- 	QTimer m_activationTimer;
- 	QPointer<class FritzingWindow> m_lastTopmostWindow;
- 	QList<QWidget *> m_orderedTopLevelWidgets;
-diff -urN fritzing-0.7.12b.source.orig/src/mainwindow/mainwindow.cpp fritzing-0.7.12b.source/src/mainwindow/mainwindow.cpp
---- fritzing-0.7.12b.source.orig/src/mainwindow/mainwindow.cpp	2013-02-25 05:02:59.000000000 -0800
-+++ fritzing-0.7.12b.source/src/mainwindow/mainwindow.cpp	2013-02-25 18:29:22.842458995 -0800
-@@ -198,7 +198,6 @@
+ public slots:
+ 	void preferences();
+ 	void preferencesAfter();
+-	void checkForUpdates();
+-	void checkForUpdates(bool atUserRequest);
+-	void enableCheckUpdates(bool enabled);
+ 	void createUserDataStoreFolderStructure();
+ 	void changeActivation(bool activate, QWidget * originator);
+ 	void updateActivation();
+@@ -182,7 +179,6 @@
+ 	QStringList m_filesToLoad;
+ 	QString m_libPath;
+ 	QString m_translationPath;
+-	class UpdateDialog * m_updateDialog;
+ 	QTimer m_activationTimer;
+ 	QPointer<class FritzingWindow> m_lastTopmostWindow;
+ 	QList<QWidget *> m_orderedTopLevelWidgets;
+diff -urN fritzing-0.8.3b.source.orig/src/mainwindow/mainwindow.cpp fritzing-0.8.3b.source/src/mainwindow/mainwindow.cpp
+--- fritzing-0.8.3b.source.orig/src/mainwindow/mainwindow.cpp	2013-07-27 14:03:38.000000000 -0700
++++ fritzing-0.8.3b.source/src/mainwindow/mainwindow.cpp	2013-08-10 22:49:23.904174341 -0700
+@@ -199,7 +199,6 @@
  	m_windowMenuSeparator = NULL;
- 	m_wireColorMenu = NULL;
+ 	m_schematicWireColorMenu = m_breadboardWireColorMenu = NULL;
  	m_viewSwitcherDock = NULL;
 -	m_checkForUpdatesAct = NULL;
  	m_fileProgressDialog = NULL;
  	m_currentGraphicsView = NULL;
  	m_comboboxChanged = false;
-@@ -1852,13 +1851,6 @@
+@@ -1897,13 +1896,6 @@
  	m_showInViewHelpAct->setChecked(show);
  }
  
@@ -145,10 +152,2898 @@ diff -urN fritzing-0.7.12b.source.orig/src/mainwindow/mainwindow.cpp fritzing-0.
  
  void MainWindow::swapSelectedDelay(const QString & family, const QString & prop, QMap<QString, QString> & currPropsMap, ItemBase * itemBase) 
  {
-diff -urN fritzing-0.7.12b.source.orig/src/mainwindow/mainwindow.h fritzing-0.7.12b.source/src/mainwindow/mainwindow.h
---- fritzing-0.7.12b.source.orig/src/mainwindow/mainwindow.h	2013-02-25 05:02:59.000000000 -0800
-+++ fritzing-0.7.12b.source/src/mainwindow/mainwindow.h	2013-02-25 18:29:22.842458995 -0800
-@@ -122,7 +122,6 @@
+diff -urN fritzing-0.8.3b.source.orig/src/mainwindow/mainwindow.cpp.orig fritzing-0.8.3b.source/src/mainwindow/mainwindow.cpp.orig
+--- fritzing-0.8.3b.source.orig/src/mainwindow/mainwindow.cpp.orig	1969-12-31 16:00:00.000000000 -0800
++++ fritzing-0.8.3b.source/src/mainwindow/mainwindow.cpp.orig	2013-07-27 14:03:38.000000000 -0700
+@@ -0,0 +1,2884 @@
++/*******************************************************************
++
++Part of the Fritzing project - http://fritzing.org
++Copyright (c) 2007-2013 Fachhochschule Potsdam - http://fh-potsdam.de
++
++Fritzing is free software: you can redistribute it and/or modify
++
++it under the terms of the GNU General Public License as published by
++the Free Software Foundation, either version 3 of the License, or
++(at your option) any later version.
++
++Fritzing is distributed in the hope that it will be useful,
++but WITHOUT ANY WARRANTY; without even the implied warranty of
++MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++GNU General Public License for more details.
++
++You should have received a copy of the GNU General Public License
++along with Fritzing.  If not, see <http://www.gnu.org/licenses/>.
++
++********************************************************************
++
++$Revision: 6995 $:
++$Author: irascibl at gmail.com $:
++$Date: 2013-04-28 00:56:34 +0200 (So, 28. Apr 2013) $
++
++********************************************************************/
++
++#include <QtGui>
++#include <QtXml>
++#include <QList>
++#include <QFileInfo>
++#include <QStringList>
++#include <QFileInfoList>
++#include <QDir>
++#include <QLabel>
++#include <QTime>
++#include <QSettings>
++#include <QRegExp>
++#include <QPaintDevice>
++#include <QPixmap>
++#include <QTimer>
++#include <QStackedWidget>
++#include <QXmlStreamReader>
++#include <QShortcut>
++
++#include "mainwindow.h"
++#include "../debugdialog.h"
++#include "../connectors/connector.h"
++#include "../partsbinpalette/partsbinpalettewidget.h"
++#include "fdockwidget.h"
++#include "../infoview/htmlinfoview.h"
++#include "../waitpushundostack.h"
++#include "../layerattributes.h"
++#include "../dock/triplenavigator.h"
++#include "../sketch/breadboardsketchwidget.h"
++#include "../sketch/schematicsketchwidget.h"
++#include "../sketch/pcbsketchwidget.h"
++#include "../svg/svgfilesplitter.h"
++#include "../utils/folderutils.h"
++#include "../utils/lockmanager.h"
++#include "../utils/textutils.h"
++#include "../utils/graphicsutils.h"
++#include "../items/mysterypart.h"
++#include "../items/moduleidnames.h"
++#include "../items/pinheader.h"
++#include "../items/perfboard.h"
++#include "../items/stripboard.h"
++#include "../items/partfactory.h"
++#include "../dock/layerpalette.h"
++#include "../items/paletteitem.h"
++#include "../items/virtualwire.h"
++#include "../items/screwterminal.h"
++#include "../items/dip.h"
++#include "../processeventblocker.h"
++#include "../help/helper.h"
++#include "../sketchtoolbutton.h"
++#include "../partsbinpalette/binmanager/binmanager.h"
++#include "../fsvgrenderer.h"
++#include "../utils/fsizegrip.h"
++#include "../utils/expandinglabel.h"
++#include "../dock/viewswitcher.h"
++#include "../dock/viewswitcherdockwidget.h"
++#include "../utils/autoclosemessagebox.h"
++#include "../utils/fileprogressdialog.h"
++#include "../utils/clickablelabel.h"
++#include "../items/resizableboard.h"
++#include "../items/resistor.h"
++#include "../items/logoitem.h"
++#include "../utils/zoomslider.h"
++#include "../partseditor/pemainwindow.h"
++
++///////////////////////////////////////////////
++
++struct MissingSvgInfo {
++    QString requestedPath;
++    QStringList connectorSvgIds;
++    ModelPart * modelPart;
++    bool equal;
++};
++
++bool byConnectorCount(MissingSvgInfo & m1, MissingSvgInfo & m2)
++{
++    if (m1.connectorSvgIds.count() == m2.connectorSvgIds.count() && m1.modelPart != m2.modelPart) {
++        m1.equal = m2.equal = true;
++    }
++
++	return (m1.connectorSvgIds.count() > m2.connectorSvgIds.count());
++}
++
++///////////////////////////////////////////////
++
++#define ZIP_PART QString("part.")
++#define ZIP_SVG  QString("svg.")
++
++///////////////////////////////////////////////
++
++// SwapTimer explained: http://code.google.com/p/fritzing/issues/detail?id=1431
++
++SwapTimer::SwapTimer() : QTimer() 
++{
++}
++
++void SwapTimer::setAll(const QString & family, const QString & prop, QMap<QString, QString> & propsMap, ItemBase * itemBase)
++{
++	m_family = family;
++	m_prop = prop;
++	m_propsMap = propsMap;
++	m_itemBase = itemBase;
++}
++
++const QString & SwapTimer::family()
++{
++	return  m_family;
++}
++
++const QString & SwapTimer::prop()
++{
++	return m_prop;
++}
++
++QMap<QString, QString> SwapTimer::propsMap()
++{
++	return m_propsMap;
++}
++
++ItemBase * SwapTimer::itemBase()
++{
++	return m_itemBase;
++}
++
++///////////////////////////////////////////////
++
++const QString MainWindow::UntitledSketchName = "Untitled Sketch";
++int MainWindow::UntitledSketchIndex = 1;
++int MainWindow::CascadeFactorX = 21;
++int MainWindow::CascadeFactorY = 19;
++
++static const int MainWindowDefaultWidth = 840;
++static const int MainWindowDefaultHeight = 600;
++
++int MainWindow::AutosaveTimeoutMinutes = 10;   // in minutes
++bool MainWindow::AutosaveEnabled = true;
++QString MainWindow::BackupFolder;
++
++QRegExp MainWindow::GuidMatcher = QRegExp("[A-Fa-f0-9]{32}");
++
++/////////////////////////////////////////////
++
++MainWindow::MainWindow(ReferenceModel *referenceModel, QWidget * parent) :
++    FritzingWindow(untitledFileName(), untitledFileCount(), fileExtension(), parent)
++{
++    m_rolloverQuoteDialog = NULL;
++	setCorner(Qt::BottomRightCorner, Qt::RightDockWidgetArea);
++	setDockOptions(QMainWindow::AnimatedDocks);
++	m_sizeGrip = new FSizeGrip(this);
++
++	m_topDock = NULL;
++	m_bottomDock = NULL;
++	m_dontKeepMargins = true;
++
++    m_settingsPrefix = "main/";
++    m_showProgramAct = m_raiseWindowAct = m_showPartsBinIconViewAct = m_showAllLayersAct = m_hideAllLayersAct = m_showInViewHelpAct = m_rotate90cwAct = m_showBreadboardAct = m_showSchematicAct = m_showPCBAct = NULL;
++    m_fileMenu = m_editMenu = m_partMenu = m_windowMenu = m_pcbTraceMenu = m_schematicTraceMenu = m_breadboardTraceMenu = m_viewMenu = NULL;
++    m_miniViewContainerBreadboard = NULL;
++    m_infoView = NULL;
++    m_addedToTemp = false;
++    setAcceptDrops(true);
++	m_activeWire = NULL;
++	m_activeConnectorItem = NULL;
++	m_swapTimer.setInterval(30);
++	m_swapTimer.setParent(this);
++	m_swapTimer.setSingleShot(true);
++	connect(&m_swapTimer, SIGNAL(timeout()), this, SLOT(swapSelectedTimeout()));
++
++	m_closeSilently = false;
++	m_orderFabAct = NULL;
++	m_viewFromButtonWidget = m_activeLayerButtonWidget = NULL;
++	m_programView = m_programWindow = NULL;
++	m_windowMenuSeparator = NULL;
++	m_schematicWireColorMenu = m_breadboardWireColorMenu = NULL;
++	m_viewSwitcherDock = NULL;
++	m_checkForUpdatesAct = NULL;
++	m_fileProgressDialog = NULL;
++	m_currentGraphicsView = NULL;
++	m_comboboxChanged = false;
++	m_helper = NULL;
++
++    // Add a timer for autosaving
++	m_backingUp = m_autosaveNeeded = false;
++    connect(&m_autosaveTimer, SIGNAL(timeout()), this, SLOT(backupSketch()));
++    m_autosaveTimer.start(AutosaveTimeoutMinutes * 60 * 1000);
++
++	resize(MainWindowDefaultWidth, MainWindowDefaultHeight);
++
++	m_backupFileNameAndPath = MainWindow::BackupFolder + "/" + TextUtils::getRandText() + FritzingSketchExtension;
++    // Connect the undoStack to our autosave stuff
++    connect(m_undoStack, SIGNAL(indexChanged(int)), this, SLOT(autosaveNeeded(int)));
++    connect(m_undoStack, SIGNAL(cleanChanged(bool)), this, SLOT(undoStackCleanChanged(bool)));
++
++	// Create dot icons
++	m_dotIcon = QIcon(":/resources/images/dot.png");
++	m_emptyIcon = QIcon();
++
++	m_currentWidget = NULL;
++	m_firstOpen = true;
++
++	m_statusBar = new QStatusBar(this);
++	setStatusBar(m_statusBar);
++	m_statusBar->setSizeGripEnabled(false);
++
++	QSettings settings;
++	m_locationLabelUnits = settings.value("LocationInches", "in").toString();
++
++	// leave the m_orderFabEnabled check in case we turn off the fab button in the future
++	m_orderFabEnabled = true; // settings.value(ORDERFABENABLED, QVariant(false)).toBool();
++
++	m_locationLabel = new ClickableLabel("", this);
++	m_locationLabel->setObjectName("LocationLabel");
++	connect(m_locationLabel, SIGNAL(clicked()), this, SLOT(locationLabelClicked()));
++    m_locationLabel->setCursor(Qt::PointingHandCursor);
++	m_statusBar->addPermanentWidget(m_locationLabel);
++
++	m_zoomSlider = new ZoomSlider(ZoomableGraphicsView::MaxScaleValue, m_statusBar);
++	connect(m_zoomSlider, SIGNAL(zoomChanged(double)), this, SLOT(updateViewZoom(double)));
++	m_statusBar->addPermanentWidget(m_zoomSlider);
++
++	setAttribute(Qt::WA_DeleteOnClose, true);
++
++#ifdef Q_WS_MAC
++        //setAttribute(Qt::WA_QuitOnClose, false);					// restoring this temporarily (2008.12.19)
++#endif
++    m_dontClose = m_closing = false;
++
++	m_referenceModel = referenceModel;
++	m_sketchModel = new SketchModel(true);
++
++
++	QShortcut * shortcut = new QShortcut(QKeySequence(tr("Ctrl+R", "Rotate Clockwise")), this);
++	connect(shortcut, SIGNAL(activated()), this, SLOT(rotateIncCW()));
++	shortcut = new QShortcut(QKeySequence(tr("Alt+Ctrl+R", "Rotate Clockwise")), this);
++	connect(shortcut, SIGNAL(activated()), this, SLOT(rotateIncCWRubberBand()));
++	shortcut = new QShortcut(QKeySequence(tr("Meta+Ctrl+R", "Rotate Clockwise")), this);
++	connect(shortcut, SIGNAL(activated()), this, SLOT(rotateIncCWRubberBand()));
++
++	shortcut = new QShortcut(QKeySequence(tr("Shift+Ctrl+R", "Rotate Counterclockwise")), this);
++	connect(shortcut, SIGNAL(activated()), this, SLOT(rotateIncCCW()));
++	shortcut = new QShortcut(QKeySequence(tr("Alt+Shift+Ctrl+R", "Rotate Counterclockwise")), this);
++	connect(shortcut, SIGNAL(activated()), this, SLOT(rotateIncCCWRubberBand()));
++	shortcut = new QShortcut(QKeySequence(tr("Meta+Shift+Ctrl+R", "Rotate Counterclockwise")), this);
++	connect(shortcut, SIGNAL(activated()), this, SLOT(rotateIncCCWRubberBand()));
++
++	shortcut = new QShortcut(QKeySequence(tr("Shift+Ctrl+Tab", "Toggle Active Layer")), this);
++	connect(shortcut, SIGNAL(activated()), this, SLOT(toggleActiveLayer()));
++
++
++	connect(this, SIGNAL(changeActivationSignal(bool, QWidget *)), qApp, SLOT(changeActivation(bool, QWidget *)), Qt::DirectConnection);
++	connect(this, SIGNAL(destroyed(QObject *)), qApp, SLOT(topLevelWidgetDestroyed(QObject *)));
++	connect(this, SIGNAL(externalProcessSignal(QString &, QString &, QStringList &)),
++			qApp, SLOT(externalProcessSlot(QString &, QString &, QStringList &)), 
++			Qt::DirectConnection);
++}
++
++QWidget * MainWindow::createTabWidget() {
++	return new QStackedWidget(this);
++}
++
++void MainWindow::addTab(QWidget * widget, const QString & label) {
++	Q_UNUSED(label);
++	qobject_cast<QStackedWidget *>(m_tabWidget)->addWidget(widget);
++}
++
++int MainWindow::currentTabIndex() {
++	return qobject_cast<QStackedWidget *>(m_tabWidget)->currentIndex();
++}
++
++void MainWindow::setCurrentTabIndex(int index) {
++	qobject_cast<QStackedWidget *>(m_tabWidget)->setCurrentIndex(index);
++}
++
++QWidget * MainWindow::currentTabWidget() {
++	return qobject_cast<QStackedWidget *>(m_tabWidget)->currentWidget();
++}
++
++void MainWindow::init(ReferenceModel *referenceModel, bool lockFiles) {
++
++	m_tabWidget = createTabWidget(); //   FTabWidget(this);
++	m_tabWidget->setObjectName("sketch_tabs");
++	setCentralWidget(m_tabWidget);
++
++    m_referenceModel = referenceModel;
++    m_restarting = false;
++
++	if (m_fileProgressDialog) {
++		m_fileProgressDialog->setValue(2);
++	}
++
++    initLockedFiles(lockFiles);
++
++    initSketchWidgets();
++    initProgrammingWidget();
++
++    m_undoView = new QUndoView();
++    m_undoGroup = new QUndoGroup(this);
++    m_undoView->setGroup(m_undoGroup);
++    m_undoGroup->setActiveStack(m_undoStack);
++
++    initDock();
++    initMenus();
++    moreInitDock();
++
++	createZoomOptions(m_breadboardWidget);
++	createZoomOptions(m_schematicWidget);
++	createZoomOptions(m_pcbWidget);
++
++    m_breadboardWidget->setToolbarWidgets(getButtonsForView(ViewLayer::BreadboardView));
++    m_schematicWidget->setToolbarWidgets(getButtonsForView(ViewLayer::SchematicView));
++	m_pcbWidget->setToolbarWidgets(getButtonsForView(ViewLayer::PCBView));
++
++    initStyleSheet();
++
++    m_breadboardGraphicsView->setItemMenu(breadboardItemMenu());
++    m_breadboardGraphicsView->setWireMenu(breadboardWireMenu());
++
++    m_pcbGraphicsView->setWireMenu(pcbWireMenu());
++    m_pcbGraphicsView->setItemMenu(pcbItemMenu());
++
++    m_schematicGraphicsView->setItemMenu(schematicItemMenu());
++    m_schematicGraphicsView->setWireMenu(schematicWireMenu());
++
++    if (m_infoView) {
++        m_breadboardGraphicsView->setInfoView(m_infoView);
++        m_pcbGraphicsView->setInfoView(m_infoView);
++        m_schematicGraphicsView->setInfoView(m_infoView);
++    }
++
++	// make sure to set the connections after the views have been created
++	connect(m_tabWidget, SIGNAL(currentChanged ( int )), this, SLOT(tabWidget_currentChanged( int )));
++
++	connectPairs();
++
++	initHelper();
++
++	// do this the first time, since the current_changed signal wasn't sent
++	int tab = 0;
++    if (m_navigators.count() > 0) {
++	    currentNavigatorChanged(m_navigators[tab]);
++    }
++	tabWidget_currentChanged(tab+1);
++	tabWidget_currentChanged(tab);
++
++	this->installEventFilter(this);
++
++	if (m_fileProgressDialog) {
++		m_fileProgressDialog->setValue(95);
++	}
++
++	QSettings settings;
++    if (m_viewSwitcherDock) {
++        m_viewSwitcherDock->prestorePreference();
++    }
++	if(!settings.value(m_settingsPrefix + "state").isNull()) {
++		restoreState(settings.value(m_settingsPrefix + "state").toByteArray());
++		restoreGeometry(settings.value(m_settingsPrefix + "geometry").toByteArray());
++	}
++    if (m_viewSwitcherDock) {
++        m_viewSwitcherDock->restorePreference();
++        m_viewSwitcherDock->setViewSwitcher(m_viewSwitcher);
++    }
++
++	setMinimumSize(0,0);
++	m_tabWidget->setMinimumWidth(500);
++	m_tabWidget->setMinimumWidth(0);
++
++    if (m_miniViewContainerBreadboard) {
++	    m_miniViewContainerBreadboard->setView(m_breadboardGraphicsView);
++	    m_miniViewContainerSchematic->setView(m_schematicGraphicsView);
++	    m_miniViewContainerPCB->setView(m_pcbGraphicsView);
++    }
++
++	connect(this, SIGNAL(readOnlyChanged(bool)), this, SLOT(applyReadOnlyChange(bool)));
++
++	m_setUpDockManagerTimer.setSingleShot(true);
++	connect(&m_setUpDockManagerTimer, SIGNAL(timeout()), this, SLOT(keepMargins()));
++    m_setUpDockManagerTimer.start(1000);
++
++	if (m_fileProgressDialog) {
++		m_fileProgressDialog->setValue(98);
++	}
++
++}
++
++MainWindow::~MainWindow()
++{
++    // Delete backup of this sketch if one exists.
++    QFile::remove(m_backupFileNameAndPath);	
++	
++	delete m_sketchModel;
++
++	dontKeepMargins();
++	m_setUpDockManagerTimer.stop();
++
++	foreach (LinkedFile * linkedFile, m_linkedProgramFiles) {
++		delete linkedFile;
++	}
++	m_linkedProgramFiles.clear();
++
++	if (!m_fzzFolder.isEmpty()) {
++		LockManager::releaseLockedFiles(m_fzzFolder, m_fzzFiles);
++		FolderUtils::rmdir(m_fzzFolder);
++	}
++}	
++
++void MainWindow::initHelper() {
++    m_helper = new Helper(this, true);
++}
++
++void MainWindow::initLockedFiles(bool lockFiles) {
++	LockManager::initLockedFiles("fzz", m_fzzFolder, m_fzzFiles, lockFiles ? LockManager::SlowTime : 0);
++	if (lockFiles) {
++		QFileInfoList backupList;
++		LockManager::checkLockedFiles("fzz", backupList, m_fzzFiles, true, LockManager::SlowTime);
++	}
++}
++
++void MainWindow::initSketchWidgets() {
++	//DebugDialog::debug("init sketch widgets");
++
++	// all this belongs in viewLayer.xml
++	m_breadboardGraphicsView = new BreadboardSketchWidget(ViewLayer::BreadboardView, this);
++	initSketchWidget(m_breadboardGraphicsView);
++	m_breadboardWidget = new SketchAreaWidget(m_breadboardGraphicsView,this);
++	addTab(m_breadboardWidget, tr("Breadboard"));
++
++	if (m_fileProgressDialog) {
++		m_fileProgressDialog->setValue(11);
++	}
++
++	m_schematicGraphicsView = new SchematicSketchWidget(ViewLayer::SchematicView, this);
++	initSketchWidget(m_schematicGraphicsView);
++	m_schematicWidget = new SketchAreaWidget(m_schematicGraphicsView, this);
++	addTab(m_schematicWidget, tr("Schematic"));
++
++	if (m_fileProgressDialog) {
++		m_fileProgressDialog->setValue(20);
++	}
++
++	m_pcbGraphicsView = new PCBSketchWidget(ViewLayer::PCBView, this);
++	initSketchWidget(m_pcbGraphicsView);
++	m_pcbWidget = new SketchAreaWidget(m_pcbGraphicsView, this);
++	addTab(m_pcbWidget, tr("PCB"));
++
++	if (m_fileProgressDialog) {
++		m_fileProgressDialog->setValue(29);
++	}
++}
++
++void MainWindow::initMenus() {
++	// This is the magic translation that changes all the shortcut text on the menu items
++	// to the native language instead of "Ctrl", so the German menu items will now read "Strg"
++	// You don't actually have to translate every menu item in the .ts file, you can just leave it as "Ctrl".
++	QShortcut::tr("Ctrl", "for naming shortcut keys on menu items");
++	QShortcut::tr("Alt", "for naming shortcut keys on menu items");
++	QShortcut::tr("Shift", "for naming shortcut keys on menu items");
++	QShortcut::tr("Meta", "for naming shortcut keys on menu items");
++
++	//DebugDialog::debug("create menus");
++
++    createActions();
++    createMenus();
++
++	//DebugDialog::debug("create toolbars");
++
++    createStatusBar();
++
++	//DebugDialog::debug("after creating status bar");
++
++	if (m_fileProgressDialog) {
++		m_fileProgressDialog->setValue(91);
++	}
++}
++
++
++				   
++
++void MainWindow::showNavigator() {
++	m_navigatorDock->setFloating(false);
++}
++
++void MainWindow::initSketchWidget(SketchWidget * sketchWidget) {
++	sketchWidget->setSketchModel(m_sketchModel);
++	sketchWidget->setReferenceModel(m_referenceModel);
++	sketchWidget->setUndoStack(m_undoStack);
++	sketchWidget->setChainDrag(true);			// enable bend points
++	sketchWidget->initGrid();
++	sketchWidget->addViewLayers();
++}
++
++void MainWindow::connectPairs() {
++	connectPair(m_breadboardGraphicsView, m_schematicGraphicsView);
++	connectPair(m_breadboardGraphicsView, m_pcbGraphicsView);
++	connectPair(m_schematicGraphicsView, m_breadboardGraphicsView);
++	connectPair(m_schematicGraphicsView, m_pcbGraphicsView);
++	connectPair(m_pcbGraphicsView, m_breadboardGraphicsView);
++	connectPair(m_pcbGraphicsView, m_schematicGraphicsView);
++
++	connect(m_pcbGraphicsView, SIGNAL(groundFillSignal()), this, SLOT(groundFill()));
++	connect(m_pcbGraphicsView, SIGNAL(copperFillSignal()), this, SLOT(copperFill()));
++
++    connect(m_pcbGraphicsView, SIGNAL(swapBoardImageSignal(SketchWidget *, ItemBase *, const QString &, const QString &, bool)),
++                this, SLOT(swapBoardImageSlot(SketchWidget *, ItemBase *, const QString &, const QString &, bool)));
++
++
++	connect(m_breadboardGraphicsView, SIGNAL(setActiveWireSignal(Wire *)), this, SLOT(setActiveWire(Wire *)));
++	connect(m_schematicGraphicsView, SIGNAL(setActiveWireSignal(Wire *)), this, SLOT(setActiveWire(Wire *)));
++	connect(m_pcbGraphicsView, SIGNAL(setActiveWireSignal(Wire *)), this, SLOT(setActiveWire(Wire *)));
++
++	connect(m_breadboardGraphicsView, SIGNAL(setActiveConnectorItemSignal(ConnectorItem *)), this, SLOT(setActiveConnectorItem(ConnectorItem *)));
++	connect(m_schematicGraphicsView, SIGNAL(setActiveConnectorItemSignal(ConnectorItem *)), this, SLOT(setActiveConnectorItem(ConnectorItem *)));
++	connect(m_pcbGraphicsView, SIGNAL(setActiveConnectorItemSignal(ConnectorItem *)), this, SLOT(setActiveConnectorItem(ConnectorItem *)));
++
++	bool succeeded = connect(m_pcbGraphicsView, SIGNAL(routingStatusSignal(SketchWidget *, const RoutingStatus &)),
++						this, SLOT(routingStatusSlot(SketchWidget *, const RoutingStatus &)));
++	succeeded =  succeeded && connect(m_schematicGraphicsView, SIGNAL(routingStatusSignal(SketchWidget *, const RoutingStatus &)),
++						this, SLOT(routingStatusSlot(SketchWidget *, const RoutingStatus &)));
++	succeeded =  succeeded && connect(m_breadboardGraphicsView, SIGNAL(routingStatusSignal(SketchWidget *, const RoutingStatus &)),
++						this, SLOT(routingStatusSlot(SketchWidget *, const RoutingStatus &)));
++
++	succeeded =  succeeded && connect(m_breadboardGraphicsView, SIGNAL(swapSignal(const QString &, const QString &, QMap<QString, QString> &, ItemBase *)), 
++						this, SLOT(swapSelectedDelay(const QString &, const QString &, QMap<QString, QString> &, ItemBase *)));
++	succeeded =  succeeded && connect(m_schematicGraphicsView, SIGNAL(swapSignal(const QString &, const QString &, QMap<QString, QString> &, ItemBase *)), 
++						this, SLOT(swapSelectedDelay(const QString &, const QString &, QMap<QString, QString> &, ItemBase *)));
++	succeeded =  succeeded && connect(m_pcbGraphicsView, SIGNAL(swapSignal(const QString &, const QString &, QMap<QString, QString> &, ItemBase *)), 
++						this, SLOT(swapSelectedDelay(const QString &, const QString &, QMap<QString, QString> &, ItemBase *)));
++
++	succeeded =  succeeded && connect(m_breadboardGraphicsView, SIGNAL(dropPasteSignal(SketchWidget *)), 
++						this, SLOT(dropPaste(SketchWidget *)));
++	succeeded =  succeeded && connect(m_schematicGraphicsView, SIGNAL(dropPasteSignal(SketchWidget *)), 
++						this, SLOT(dropPaste(SketchWidget *)));
++	succeeded =  succeeded && connect(m_pcbGraphicsView, SIGNAL(dropPasteSignal(SketchWidget *)), 
++						this, SLOT(dropPaste(SketchWidget *)));
++	
++	succeeded =  succeeded && connect(m_pcbGraphicsView, SIGNAL(subSwapSignal(SketchWidget *, ItemBase *, const QString &, ViewLayer::ViewLayerPlacement, long &, QUndoCommand *)),
++						this, SLOT(subSwapSlot(SketchWidget *, ItemBase *, const QString &, ViewLayer::ViewLayerPlacement, long &, QUndoCommand *)),
++						Qt::DirectConnection);
++
++	succeeded =  succeeded && connect(m_pcbGraphicsView, SIGNAL(firstTimeHelpHidden()), this, SLOT(firstTimeHelpHidden()));
++	succeeded =  succeeded && connect(m_schematicGraphicsView, SIGNAL(firstTimeHelpHidden()), this, SLOT(firstTimeHelpHidden()));
++	succeeded =  succeeded && connect(m_breadboardGraphicsView, SIGNAL(firstTimeHelpHidden()), this, SLOT(firstTimeHelpHidden()));
++
++	succeeded =  succeeded && connect(m_pcbGraphicsView, SIGNAL(updateLayerMenuSignal()), this, SLOT(updateLayerMenuSlot()));
++	succeeded =  succeeded && connect(m_pcbGraphicsView, SIGNAL(changeBoardLayersSignal(int, bool )), this, SLOT(changeBoardLayers(int, bool )));
++
++	succeeded =  succeeded && connect(m_pcbGraphicsView, SIGNAL(boardDeletedSignal()), this, SLOT(boardDeletedSlot()));
++
++	succeeded =  succeeded && connect(qApp, SIGNAL(spaceBarIsPressedSignal(bool)), m_breadboardGraphicsView, SLOT(spaceBarIsPressedSlot(bool)));
++	succeeded =  succeeded && connect(qApp, SIGNAL(spaceBarIsPressedSignal(bool)), m_schematicGraphicsView, SLOT(spaceBarIsPressedSlot(bool)));
++	succeeded =  succeeded && connect(qApp, SIGNAL(spaceBarIsPressedSignal(bool)), m_pcbGraphicsView, SLOT(spaceBarIsPressedSlot(bool)));
++
++	succeeded =  succeeded && connect(m_pcbGraphicsView, SIGNAL(cursorLocationSignal(double, double)), this, SLOT(cursorLocationSlot(double, double)));
++	succeeded =  succeeded && connect(m_breadboardGraphicsView, SIGNAL(cursorLocationSignal(double, double)), this, SLOT(cursorLocationSlot(double, double)));
++	succeeded =  succeeded && connect(m_schematicGraphicsView, SIGNAL(cursorLocationSignal(double, double)), this, SLOT(cursorLocationSlot(double, double)));
++
++	succeeded =  succeeded && connect(m_breadboardGraphicsView, SIGNAL(filenameIfSignal(QString &)), this, SLOT(filenameIfSlot(QString &)), Qt::DirectConnection);
++	succeeded =  succeeded && connect(m_pcbGraphicsView, SIGNAL(filenameIfSignal(QString &)), this, SLOT(filenameIfSlot(QString &)), Qt::DirectConnection);
++	succeeded =  succeeded && connect(m_schematicGraphicsView, SIGNAL(filenameIfSignal(QString &)), this, SLOT(filenameIfSlot(QString &)), Qt::DirectConnection);
++	
++
++
++    succeeded =  succeeded && connect(m_breadboardGraphicsView, SIGNAL(getDroppedItemViewLayerPlacementSignal(ModelPart *, ViewLayer::ViewLayerPlacement &)), 
++                                        m_pcbGraphicsView, SLOT(getDroppedItemViewLayerPlacement(ModelPart *, ViewLayer::ViewLayerPlacement &)), 
++                                        Qt::DirectConnection);
++    succeeded =  succeeded && connect(m_schematicGraphicsView, SIGNAL(getDroppedItemViewLayerPlacementSignal(ModelPart *, ViewLayer::ViewLayerPlacement &)), 
++                                        m_pcbGraphicsView, SLOT(getDroppedItemViewLayerPlacement(ModelPart *, ViewLayer::ViewLayerPlacement &)), 
++                                        Qt::DirectConnection);
++
++
++    if (!succeeded) {
++		DebugDialog::debug("connectPair failed");
++	}
++}
++
++void MainWindow::connectPair(SketchWidget * signaller, SketchWidget * slotter)
++{
++
++	bool succeeded = connect(signaller, SIGNAL(itemAddedSignal(ModelPart *, ItemBase *, ViewLayer::ViewLayerPlacement, const ViewGeometry &, long, SketchWidget *)),
++							 slotter, SLOT(itemAddedSlot(ModelPart *, ItemBase *, ViewLayer::ViewLayerPlacement, const ViewGeometry &, long, SketchWidget *)));
++
++	succeeded = succeeded && connect(signaller, SIGNAL(itemDeletedSignal(long)),
++									 slotter, SLOT(itemDeletedSlot(long)),
++									 Qt::DirectConnection);
++
++	succeeded = succeeded && connect(signaller, SIGNAL(clearSelectionSignal()),
++									 slotter, SLOT(clearSelectionSlot()));
++
++	succeeded = succeeded && connect(signaller, SIGNAL(itemSelectedSignal(long, bool)),
++									 slotter, SLOT(itemSelectedSlot(long, bool)));
++	succeeded = succeeded && connect(signaller, SIGNAL(selectAllItemsSignal(bool, bool)),
++									 slotter, SLOT(selectAllItems(bool, bool)));
++	succeeded = succeeded && connect(signaller, SIGNAL(wireDisconnectedSignal(long, QString)),
++									 slotter, SLOT(wireDisconnectedSlot(long,  QString)));
++	succeeded = succeeded && connect(signaller, SIGNAL(wireConnectedSignal(long,  QString, long,  QString)),
++									 slotter, SLOT(wireConnectedSlot(long, QString, long, QString)));
++	succeeded = succeeded && connect(signaller, SIGNAL(changeConnectionSignal(long,  QString, long,  QString, ViewLayer::ViewLayerPlacement, bool, bool)),
++									 slotter, SLOT(changeConnectionSlot(long, QString, long, QString, ViewLayer::ViewLayerPlacement, bool, bool)));
++	succeeded = succeeded && connect(signaller, SIGNAL(copyBoundingRectsSignal(QHash<QString, QRectF> &)),
++													   slotter, SLOT(copyBoundingRectsSlot(QHash<QString, QRectF> &)),
++									 Qt::DirectConnection);
++
++	succeeded = succeeded && connect(signaller, SIGNAL(cleanUpWiresSignal(CleanUpWiresCommand *)),
++									 slotter, SLOT(cleanUpWiresSlot(CleanUpWiresCommand *)) );
++
++	succeeded = succeeded && connect(signaller, SIGNAL(cleanupRatsnestsSignal(bool)),
++									 slotter, SLOT(cleanupRatsnests(bool)) );
++
++	succeeded = succeeded && connect(signaller, SIGNAL(checkStickySignal(long, bool, bool, CheckStickyCommand *)),
++									 slotter, SLOT(checkSticky(long, bool, bool, CheckStickyCommand *)) );
++
++	succeeded = succeeded && connect(signaller, SIGNAL(disconnectAllSignal(QList<ConnectorItem *>, QHash<ItemBase *, SketchWidget *> &, QUndoCommand *)),
++									 slotter, SLOT(disconnectAllSlot(QList<ConnectorItem *>, QHash<ItemBase *, SketchWidget *> &, QUndoCommand *)),
++									 Qt::DirectConnection);
++	succeeded = succeeded && connect(signaller, SIGNAL(setResistanceSignal(long, QString, QString, bool)),
++									 slotter, SLOT(setResistance(long, QString, QString, bool)));
++	succeeded = succeeded && connect(signaller, SIGNAL(makeDeleteItemCommandPrepSignal(ItemBase *, bool , QUndoCommand * )),
++									 slotter, SLOT(makeDeleteItemCommandPrepSlot(ItemBase * , bool , QUndoCommand * )));
++	succeeded = succeeded && connect(signaller, SIGNAL(makeDeleteItemCommandFinalSignal(ItemBase *, bool , QUndoCommand * )),
++									 slotter, SLOT(makeDeleteItemCommandFinalSlot(ItemBase * , bool , QUndoCommand * )));
++
++	succeeded = succeeded && connect(signaller, SIGNAL(setPropSignal(long,  const QString &,  const QString &, bool, bool)),
++									 slotter, SLOT(setProp(long,  const QString &,  const QString &, bool, bool)));
++
++	succeeded = succeeded && connect(signaller, SIGNAL(setInstanceTitleSignal(long, const QString &, const QString &, bool, bool )),
++									 slotter, SLOT(setInstanceTitle(long, const QString &, const QString &, bool, bool )));
++
++	succeeded = succeeded && connect(signaller, SIGNAL(setVoltageSignal(double, bool )),
++									 slotter, SLOT(setVoltage(double, bool )));
++
++	succeeded = succeeded && connect(signaller, SIGNAL(showLabelFirstTimeSignal(long, bool, bool )),
++									 slotter, SLOT(showLabelFirstTime(long, bool, bool )));
++
++	succeeded = succeeded && connect(signaller, SIGNAL(changeBoardLayersSignal(int, bool )),
++									 slotter, SLOT(changeBoardLayers(int, bool )));
++
++	succeeded = succeeded && connect(signaller, SIGNAL(deleteTracesSignal(QSet<ItemBase *> &, QHash<ItemBase *, SketchWidget *> &, QList<long> &, bool, QUndoCommand *)),
++									 slotter, SLOT(deleteTracesSlot(QSet<ItemBase *> &, QHash<ItemBase *, SketchWidget *> &, QList<long> &, bool, QUndoCommand *)),
++									 Qt::DirectConnection);
++
++	succeeded = succeeded && connect(signaller, SIGNAL(ratsnestConnectSignal(long, const QString &, bool, bool)),
++									 slotter, SLOT(ratsnestConnect(long, const QString &, bool, bool )),
++									 Qt::DirectConnection);
++
++
++	succeeded = succeeded && connect(signaller, SIGNAL(updatePartLabelInstanceTitleSignal(long)),
++									 slotter, SLOT(updatePartLabelInstanceTitleSlot(long)));
++
++	succeeded = succeeded && connect(signaller, SIGNAL(changePinLabelsSignal(ItemBase *, bool)),
++									 slotter, SLOT(changePinLabelsSlot(ItemBase *, bool)));
++
++	succeeded = succeeded && connect(signaller, SIGNAL(collectRatsnestSignal(QList<SketchWidget *> &)),
++									 slotter, SLOT(collectRatsnestSlot(QList<SketchWidget *> &)),
++									 Qt::DirectConnection);
++
++	succeeded = succeeded && connect(signaller, SIGNAL(removeRatsnestSignal(QList<struct ConnectorEdge *> &, QUndoCommand *)),
++									 slotter, SLOT(removeRatsnestSlot(QList<struct ConnectorEdge *> &, QUndoCommand *)),
++									 Qt::DirectConnection);
++
++	succeeded = succeeded && connect(signaller, SIGNAL(canConnectSignal(Wire *, ItemBase *, bool &)),
++									 slotter, SLOT(canConnect(Wire *, ItemBase *, bool &)),
++									 Qt::DirectConnection);
++
++	succeeded = succeeded && connect(signaller, SIGNAL(swapStartSignal(SwapThing &, bool)),
++									 slotter, SLOT(swapStart(SwapThing &, bool)),
++									 Qt::DirectConnection);
++
++	succeeded = succeeded && connect(signaller, SIGNAL(packItemsSignal(int, const QList<long> &, QUndoCommand *, bool)),
++									 slotter, SLOT(packItems(int, const QList<long> &, QUndoCommand *, bool)));
++
++	succeeded = succeeded && connect(signaller, SIGNAL(addSubpartSignal(long, long, bool)), slotter, SLOT(addSubpart(long, long, bool)));
++
++	if (!succeeded) {
++		DebugDialog::debug("connectPair failed");
++	}
++
++}
++
++void MainWindow::setCurrentFile(const QString &filename, bool addToRecent, bool setAsLastOpened) {
++	setFileName(filename);
++
++	if(setAsLastOpened) {
++		QSettings settings;
++		settings.setValue("lastOpenSketch",filename);
++	}
++
++	updateRaiseWindowAction();
++	setTitle();
++
++	if(addToRecent) {
++		QSettings settings;
++		QStringList files = settings.value("recentFileList").toStringList();
++		files.removeAll(filename);
++		files.prepend(filename);
++		while (files.size() > MaxRecentFiles)
++			files.removeLast();
++
++		settings.setValue("recentFileList", files);
++	}
++
++    foreach (QWidget *widget, QApplication::topLevelWidgets()) {
++        MainWindow *mainWin = qobject_cast<MainWindow *>(widget);
++        if (mainWin)
++            mainWin->updateRecentFileActions();
++    }
++}
++
++
++void MainWindow::createZoomOptions(SketchAreaWidget* parent) {
++
++    connect(parent->contentView(), SIGNAL(zoomChanged(double)), this, SLOT(updateZoomSlider(double)));
++    connect(parent->contentView(), SIGNAL(zoomOutOfRange(double)), this, SLOT(updateZoomOptionsNoMatterWhat(double)));
++}
++
++ExpandingLabel * MainWindow::createRoutingStatusLabel(SketchAreaWidget * parent) {
++	ExpandingLabel * routingStatusLabel = new ExpandingLabel(m_pcbWidget);
++
++	connect(routingStatusLabel, SIGNAL(mousePressSignal(QMouseEvent*)), this, SLOT(routingStatusLabelMousePress(QMouseEvent*)));
++	connect(routingStatusLabel, SIGNAL(mouseReleaseSignal(QMouseEvent*)), this, SLOT(routingStatusLabelMouseRelease(QMouseEvent*)));
++
++	routingStatusLabel->setTextInteractionFlags(Qt::NoTextInteraction);
++	routingStatusLabel->setCursor(Qt::WhatsThisCursor);
++	routingStatusLabel->viewport()->setCursor(Qt::WhatsThisCursor);
++
++	routingStatusLabel->setObjectName(SketchAreaWidget::RoutingStateLabelName);
++	parent->setRoutingStatusLabel(routingStatusLabel);
++	RoutingStatus routingStatus;
++	routingStatus.zero();
++	routingStatusSlot(qobject_cast<SketchWidget *>(parent->contentView()), routingStatus);
++	return routingStatusLabel;
++}
++
++SketchToolButton *MainWindow::createRotateButton(SketchAreaWidget *parent) {
++	QList<QAction*> rotateMenuActions;
++	rotateMenuActions << m_rotate45ccwAct << m_rotate90ccwAct << m_rotate180Act << m_rotate90cwAct << m_rotate45cwAct;
++	SketchToolButton * rotateButton = new SketchToolButton("Rotate",parent, rotateMenuActions);
++	rotateButton->setDefaultAction(m_rotate90ccwAct);
++	rotateButton->setText(tr("Rotate"));
++
++	m_rotateButtons << rotateButton;
++	return rotateButton;
++}
++
++SketchToolButton *MainWindow::createShareButton(SketchAreaWidget *parent) {
++	SketchToolButton *shareButton = new SketchToolButton("Share",parent, m_shareOnlineAct);
++	shareButton->setText(tr("Share"));
++	shareButton->setEnabledIcon();					// seems to need this to display button icon first time
++	return shareButton;
++}
++
++SketchToolButton *MainWindow::createFlipButton(SketchAreaWidget *parent) {
++	QList<QAction*> flipMenuActions;
++	flipMenuActions << m_flipHorizontalAct << m_flipVerticalAct;
++	SketchToolButton *flipButton = new SketchToolButton("Flip",parent, flipMenuActions);
++	flipButton->setText(tr("Flip"));
++
++	m_flipButtons << flipButton;
++	return flipButton;
++}
++
++SketchToolButton *MainWindow::createAutorouteButton(SketchAreaWidget *parent) {
++	SketchToolButton *autorouteButton = new SketchToolButton("Autoroute",parent, m_newAutorouteAct);
++	autorouteButton->setText(tr("Autoroute"));
++	autorouteButton->setEnabledIcon();					// seems to need this to display button icon first time
++
++	return autorouteButton;
++}
++
++SketchToolButton *MainWindow::createOrderFabButton(SketchAreaWidget *parent) {
++	SketchToolButton *orderFabButton = new SketchToolButton("Order",parent, m_orderFabAct);
++	orderFabButton->setText(tr("Order PCB"));
++	orderFabButton->setEnabledIcon();					// seems to need this to display button icon first time
++
++	return orderFabButton;
++}
++
++QWidget *MainWindow::createActiveLayerButton(SketchAreaWidget *parent) 
++{
++	QList<QAction *> actions;
++	actions << m_activeLayerBothAct << m_activeLayerBottomAct << m_activeLayerTopAct;
++
++	m_activeLayerButtonWidget = new QStackedWidget;
++	m_activeLayerButtonWidget->setMaximumWidth(90);
++
++	SketchToolButton * button = new SketchToolButton("ActiveLayer", parent, actions);
++	button->setDefaultAction(m_activeLayerBottomAct);
++	button->setText(tr("Both Layers"));
++	m_activeLayerButtonWidget->addWidget(button);
++
++	button = new SketchToolButton("ActiveLayerB", parent, actions);
++	button->setDefaultAction(m_activeLayerTopAct);
++	button->setText(tr("Bottom Layer"));
++	m_activeLayerButtonWidget->addWidget(button);
++
++	button = new SketchToolButton("ActiveLayerT", parent, actions);
++	button->setDefaultAction(m_activeLayerBothAct);
++	button->setText(tr("Top Layer"));
++	m_activeLayerButtonWidget->addWidget(button);
++
++	return m_activeLayerButtonWidget;
++}
++
++QWidget *MainWindow::createViewFromButton(SketchAreaWidget *parent) 
++{
++	QList<QAction *> actions;
++	actions << m_viewFromAboveAct << m_viewFromBelowAct;
++
++	m_viewFromButtonWidget = new QStackedWidget;
++	m_viewFromButtonWidget->setMaximumWidth(90);
++
++	SketchToolButton * button = new SketchToolButton("ViewFromT", parent, actions);
++	button->setDefaultAction(m_viewFromBelowAct);
++	button->setText(tr("View from Above"));
++    button->setEnabledIcon();					// seems to need this to display button icon first time
++
++	m_viewFromButtonWidget->addWidget(button);
++
++	button = new SketchToolButton("ViewFromB", parent, actions);
++	button->setDefaultAction(m_viewFromAboveAct);
++	button->setText(tr("View from Below"));
++    button->setEnabledIcon();					// seems to need this to display button icon first time
++	m_viewFromButtonWidget->addWidget(button);
++
++	return m_viewFromButtonWidget;
++}
++
++SketchToolButton *MainWindow::createNoteButton(SketchAreaWidget *parent) {
++	SketchToolButton *noteButton = new SketchToolButton("Notes",parent, m_addNoteAct);
++	noteButton->setText(tr("Add a note"));
++	noteButton->setEnabledIcon();					// seems to need this to display button icon first time
++	return noteButton;
++}
++
++SketchToolButton *MainWindow::createExportEtchableButton(SketchAreaWidget *parent) {
++	QList<QAction*> actions;
++	actions << m_exportEtchablePdfAct << m_exportEtchableSvgAct << m_exportGerberAct;
++	SketchToolButton *exportEtchableButton = new SketchToolButton("Diy",parent, actions);
++	exportEtchableButton->setDefaultAction(m_exportEtchablePdfAct);
++	exportEtchableButton->setText(tr("Export for PCB"));
++	exportEtchableButton->setEnabledIcon();				// seems to need this to display button icon first time
++	return exportEtchableButton;
++}
++
++QWidget *MainWindow::createToolbarSpacer(SketchAreaWidget *parent) {
++	QFrame *toolbarSpacer = new QFrame(parent);
++	QHBoxLayout *spacerLayout = new QHBoxLayout(toolbarSpacer);
++	spacerLayout->addSpacerItem(new QSpacerItem(0,0,QSizePolicy::Expanding));
++
++	return toolbarSpacer;
++}
++
++QList<QWidget*> MainWindow::getButtonsForView(ViewLayer::ViewID viewId) {
++	QList<QWidget*> retval;
++	SketchAreaWidget *parent;
++	switch(viewId) {
++		case ViewLayer::BreadboardView: parent = m_breadboardWidget; break;
++		case ViewLayer::SchematicView: parent = m_schematicWidget; break;
++		case ViewLayer::PCBView: parent = m_pcbWidget; break;
++		default: return retval;
++	}
++	retval << createShareButton(parent);
++
++	switch(viewId) {
++		case ViewLayer::BreadboardView:
++		case ViewLayer::SchematicView:
++			retval << createNoteButton(parent);
++		default: 
++			break;
++	}
++	
++	retval << createRotateButton(parent);
++	switch (viewId) {
++		case ViewLayer::BreadboardView:
++			retval << createFlipButton(parent); 
++			break;
++		case ViewLayer::SchematicView:
++			retval << createFlipButton(parent) << createToolbarSpacer(parent) << createAutorouteButton(parent);
++			break;
++		case ViewLayer::PCBView:
++			retval << SketchAreaWidget::separator(parent) 
++                << createViewFromButton(parent)
++				<< createActiveLayerButton(parent) 
++				<< createAutorouteButton(parent) 
++				<< createExportEtchableButton(parent);
++			if (m_orderFabEnabled) {
++                SketchToolButton * orderFabButton = createOrderFabButton(parent);
++				retval << orderFabButton;
++                connect(orderFabButton, SIGNAL(entered()), this, SLOT(orderFabHoverEnter()));
++                connect(orderFabButton, SIGNAL(left()), this, SLOT(orderFabHoverLeave()));
++			}
++
++
++			break;
++		default:
++			break;
++	}
++
++	retval << createRoutingStatusLabel(parent);
++	return retval;
++}
++
++void MainWindow::updateZoomSlider(double zoom) {
++	m_zoomSlider->setValue(zoom);
++}
++
++SketchAreaWidget *MainWindow::currentSketchArea() {
++	return dynamic_cast<SketchAreaWidget*>(m_currentGraphicsView->parent());
++}
++
++void MainWindow::updateZoomOptionsNoMatterWhat(double zoom) {
++	m_zoomSlider->setValue(zoom);
++}
++
++void MainWindow::updateViewZoom(double newZoom) {
++	m_comboboxChanged = true;
++	if(m_currentGraphicsView) m_currentGraphicsView->absoluteZoom(newZoom);
++}
++
++
++void MainWindow::createStatusBar()
++{
++    m_statusBar->showMessage(tr("Ready"));
++}
++
++void MainWindow::tabWidget_currentChanged(int index) {
++	SketchAreaWidget * widgetParent = dynamic_cast<SketchAreaWidget *>(currentTabWidget());
++	if (widgetParent == NULL) return;
++
++	m_currentWidget = widgetParent;
++
++	if (m_locationLabel) {
++		m_locationLabel->setText("");
++	}
++
++	QStatusBar *sb = statusBar();
++	connect(sb, SIGNAL(messageChanged(const QString &)), this, SLOT(showStatusMessage(const QString &)));
++	widgetParent->addStatusBar(m_statusBar);
++	if(sb != m_statusBar) sb->hide();
++
++	if (m_breadboardGraphicsView) m_breadboardGraphicsView->setCurrent(false);
++	if (m_schematicGraphicsView) m_schematicGraphicsView->setCurrent(false);
++	if (m_pcbGraphicsView) m_pcbGraphicsView->setCurrent(false);
++
++	SketchWidget *widget = qobject_cast<SketchWidget *>(widgetParent->contentView());
++
++	if(m_currentGraphicsView) {
++		m_currentGraphicsView->saveZoom(m_zoomSlider->value());
++		disconnect(
++			m_currentGraphicsView,
++			SIGNAL(selectionChangedSignal()),
++			this,
++			SLOT(updateTransformationActions())
++		);
++	}
++	m_currentGraphicsView = widget;
++
++    if (m_programView) {
++        hideShowProgramMenu();
++    }
++
++	hideShowTraceMenu();
++
++    if (m_showBreadboardAct) {
++	    QList<QAction *> actions;
++	    actions << m_showBreadboardAct << m_showSchematicAct << m_showPCBAct;
++        if (m_programView) actions << m_showProgramAct;
++	    setActionsIcons(index, actions);
++    }
++
++	if (widget == NULL) return;
++
++	m_zoomSlider->setValue(m_currentGraphicsView->retrieveZoom());
++
++	connect(
++		m_currentGraphicsView,					// don't connect directly to the scene here, connect to the widget's signal
++		SIGNAL(selectionChangedSignal()),
++		this,
++		SLOT(updateTransformationActions())
++	);
++
++	updateActiveLayerButtons();
++
++	m_currentGraphicsView->setCurrent(true);
++
++	// !!!!!! hack alert  !!!!!!!  
++	// this item update loop seems to deal with a qt update bug:
++	// if one view is visible and you change something in another view, 
++	// the change might not appear when you switch views until you move the item in question
++	foreach(QGraphicsItem * item, m_currentGraphicsView->items()) {
++		item->update();
++	}
++
++	updateLayerMenu(true);
++	updateTraceMenu();
++	updateTransformationActions();
++
++	setTitle();
++
++	// triggers a signal to the navigator widget
++    if (m_navigators.count() > index) {
++	    m_navigators[index]->miniViewMousePressedSlot();
++    }
++	emit viewSwitched(index);
++
++    if (m_showInViewHelpAct) {
++	    if (m_helper == NULL) {
++		    m_showInViewHelpAct->setChecked(false);
++	    }
++	    else {
++		    m_showInViewHelpAct->setChecked(m_helper->helpVisible(currentTabIndex()));
++	    }
++    }
++
++    if (m_infoView) {
++	    m_currentGraphicsView->updateInfoView();
++    }
++
++	// update issue with 4.5.1?: is this still valid (4.6.x?)
++	m_currentGraphicsView->updateConnectors();
++
++}
++
++void MainWindow::setActionsIcons(int index, QList<QAction *> & actions) {
++	for (int i = 0; i < actions.count(); i++) {
++		actions[i]->setIcon(index == i ? m_dotIcon : m_emptyIcon);
++	}
++}
++
++void MainWindow::closeEvent(QCloseEvent *event) {
++	if (m_dontClose) {
++		event->ignore();
++		return;
++	}
++
++	if (m_programWindow) {
++		m_programWindow->close();
++		if (m_programWindow->isVisible()) {
++			event->ignore();
++			return;
++		}
++	}
++
++	if (!m_closeSilently) {
++		bool whatWithAliens = whatToDoWithAlienFiles();
++		bool discard;
++		if(!beforeClosing(true, discard) || !whatWithAliens ||!m_binManager->beforeClosing()) {
++			event->ignore();
++			return;
++		}
++
++		if(whatWithAliens && m_binManager->hasAlienParts()) {
++			m_binManager->createIfMyPartsNotExists();
++		}
++	}
++
++	//DebugDialog::debug(QString("top level windows: %1").arg(QApplication::topLevelWidgets().size()));
++	/*
++	foreach (QWidget * widget, QApplication::topLevelWidgets()) {
++		QMenu * menu = qobject_cast<QMenu *>(widget);
++		if (menu != NULL) {
++			continue;				// QMenus are always top level widgets, even if they have parents...
++		}
++		DebugDialog::debug(QString("top level widget %1 %2 %3")
++			.arg(widget->metaObject()->className())
++			.arg(widget->windowTitle())
++			.arg(widget->toolTip())
++			);
++	}
++	*/
++
++	m_closing = true;
++
++	int count = 0;
++	foreach (QWidget *widget, QApplication::topLevelWidgets()) {
++		if (widget == this) continue;
++		if (qobject_cast<QMainWindow *>(widget) == NULL) continue;
++
++		count++;
++	}
++
++	if (count == 0) {
++		DebugDialog::closeDebug();
++	}
++
++	QSettings settings;
++	settings.setValue(m_settingsPrefix + "state",saveState());
++	settings.setValue(m_settingsPrefix + "geometry",saveGeometry());
++
++	QMainWindow::closeEvent(event);
++}
++
++bool MainWindow::whatToDoWithAlienFiles() {
++	if (m_alienFiles.size() > 0) {
++        QString basename = QFileInfo(m_fwFilename).fileName();
++		QMessageBox::StandardButton reply;
++		reply = QMessageBox::question(this, tr("Save %1").arg(basename),
++						 m_alienPartsMsg
++						 .arg(basename),
++						 QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel);
++		// TODO: translate button text
++		if (reply == QMessageBox::Yes) {
++			return true;
++		} else if (reply == QMessageBox::No) {
++			foreach(QString pathToRemove, m_alienFiles) {
++				QFile::remove(pathToRemove);
++			}
++			m_alienFiles.clear();
++			recoverBackupedFiles();
++
++			emit alienPartsDismissed();
++			return true;
++		}
++		else {
++			return false;
++		}
++	} else {
++		return true;
++	}
++}
++
++void MainWindow::acceptAlienFiles() {
++	m_alienFiles.clear();
++}
++
++bool MainWindow::eventFilter(QObject *object, QEvent *event) {
++	if (object == this &&
++		(event->type() == QEvent::KeyPress
++		// || event->type() == QEvent::KeyRelease
++		|| event->type() == QEvent::ShortcutOverride))
++	{
++		//DebugDialog::debug(QString("event filter %1").arg(event->type()) );
++		updatePartMenu();
++		updateTraceMenu();
++
++		// On the mac, the first time the delete key is pressed, to be used as a shortcut for QAction m_deleteAct,
++		// for some reason, the enabling of the m_deleteAct in UpdateEditMenu doesn't "take" until the next time the event loop is processed
++		// Thereafter, the delete key works as it should.
++		// So this call to processEvents() makes sure m_deleteAct is enabled.
++		ProcessEventBlocker::processEvents();
++	}
++
++	return QMainWindow::eventFilter(object, event);
++}
++
++const QString MainWindow::untitledFileName() {
++	return UntitledSketchName;
++}
++
++int &MainWindow::untitledFileCount() {
++	return UntitledSketchIndex;
++}
++
++const QString MainWindow::fileExtension() {
++	return FritzingBundleExtension;
++}
++
++const QString MainWindow::defaultSaveFolder() {
++	return FolderUtils::openSaveFolder();
++}
++
++bool MainWindow::undoStackIsEmpty() {
++	return m_undoStack->count() == 0;
++}
++
++void MainWindow::setInfoViewOnHover(bool infoViewOnHover) {
++	m_breadboardGraphicsView->setInfoViewOnHover(infoViewOnHover);
++	m_schematicGraphicsView->setInfoViewOnHover(infoViewOnHover);
++	m_pcbGraphicsView->setInfoViewOnHover(infoViewOnHover);
++
++	m_binManager->setInfoViewOnHover(infoViewOnHover);
++}
++
++void MainWindow::loadBundledSketch(const QString &fileName, bool addToRecent, bool setAsLastOpened) {
++
++    QString error;
++	if(!FolderUtils::unzipTo(fileName, m_fzzFolder, error)) {
++		QMessageBox::warning(
++			this,
++			tr("Fritzing"),
++			tr("Unable to open '%1': %2").arg(fileName).arg(error)
++		);
++
++		return;
++	}
++
++	QDir dir(m_fzzFolder);
++    QString binFileName = dir.absoluteFilePath(QFileInfo(BinManager::TempPartsBinTemplateLocation).fileName());
++    m_binManager->setTempPartsBinLocation(binFileName);
++    FolderUtils::copyBin(binFileName, BinManager::TempPartsBinTemplateLocation);
++
++	QStringList namefilters;
++	namefilters << "*"+FritzingSketchExtension;
++	QFileInfoList entryInfoList = dir.entryInfoList(namefilters);
++	if (entryInfoList.count() == 0) {
++		QMessageBox::warning(
++			this,
++			tr("Fritzing"),
++			tr("No Sketch found in '%1'").arg(fileName)
++		);
++
++		return;
++	}
++
++	QFileInfo sketchInfo = entryInfoList[0];
++
++	QString sketchName = dir.absoluteFilePath(sketchInfo.fileName());
++
++    namefilters.clear();
++    namefilters << "*" + FritzingPartExtension;
++    entryInfoList = dir.entryInfoList(namefilters);
++
++    namefilters.clear();
++	namefilters << "*.svg";
++	QFileInfoList svgEntryInfoList = dir.entryInfoList(namefilters);
++
++    m_addedToTemp = false;
++
++    QList<MissingSvgInfo> missing;
++    QList<ModelPart *> missingModelParts;
++
++    foreach (QFileInfo fzpInfo, entryInfoList) {
++        QFile file(dir.absoluteFilePath(fzpInfo.fileName()));
++        if (!file.open(QFile::ReadOnly)) {
++            DebugDialog::debug(QString("unable to open %1: %2").arg(file.fileName()));
++            continue;
++        }
++
++        // TODO: could be more efficient by using a streamreader
++        QString fzp = file.readAll();
++        file.close();
++
++        QString moduleID = TextUtils::parseForModuleID(fzp);
++        if (moduleID.isEmpty()) {
++            DebugDialog::debug("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
++            DebugDialog::debug(QString("unable to find module id in %1: %2").arg(file.fileName()).arg(fzp));
++            DebugDialog::debug("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
++            continue;
++        }
++
++        ModelPart * mp = m_referenceModel->retrieveModelPart(moduleID);
++        if (mp == NULL) {
++            QDomDocument doc;
++            if (!doc.setContent(fzp)) {
++                DebugDialog::debug(QString("unable to parse fzp in %1: %2").arg(file.fileName()).arg(fzp));
++                continue;
++            }
++
++            mp = copyToPartsFolder(fzpInfo, false, PartFactory::folderPath(), "contrib");
++            if (mp == NULL) {
++                DebugDialog::debug(QString("unable to create model part in %1: %2").arg(file.fileName()).arg(fzp));
++                continue;
++            }
++
++            QDomElement root = doc.documentElement();
++	        QDomElement views = root.firstChildElement("views");
++	        QDomElement view = views.firstChildElement();
++            while (!view.isNull()) {
++                QDomElement layers = view.firstChildElement("layers");
++                QString path = layers.attribute("image", "");
++                if (!path.isEmpty()) {
++                    bool copied = copySvg(path, svgEntryInfoList);
++                    if (!copied) {
++                        DebugDialog::debug(QString("missing svg %1").arg(path));
++                        MissingSvgInfo msi;
++                        msi.equal = false;
++                        msi.modelPart = mp;
++                        missingModelParts << mp;
++                        msi.requestedPath = path;
++                        ViewLayer::ViewID viewID = ViewLayer::idFromXmlName(view.tagName());
++                        QDomElement connectors = root.firstChildElement("connectors");
++                        QDomElement connector = connectors.firstChildElement("connector");
++                        while (!connector.isNull()) {
++                            QString id, terminalID;
++                            ViewLayer::getConnectorSvgIDs(connector, viewID, id, terminalID);
++                            if (!id.isEmpty()) {
++                                msi.connectorSvgIds.append(id);
++                            }
++                            connector = connector.nextSiblingElement("connector");
++                        }
++                        missing << msi;
++                    }
++                }
++                view = view.nextSiblingElement();
++            }
++
++        	mp->setFzz(true);
++        }
++
++        if (!missingModelParts.contains(mp)) {
++		    m_binManager->addToTempPartsBin(mp);
++            m_addedToTemp = true;
++        }
++    }
++
++    qSort(missing.begin(), missing.end(), byConnectorCount);
++    foreach (MissingSvgInfo msi, missing) {
++        if (msi.equal) {
++            // two or more parts have the same number of connectors--so we can't figure out how to assign them
++            continue;
++        }
++
++        int slash = msi.requestedPath.indexOf("/");
++        QString suffix = msi.requestedPath.mid(slash + 1);
++        QString prefix = msi.requestedPath.left(slash);
++        for (int jx = svgEntryInfoList.count() - 1; jx >= 0; jx--) {
++            QFileInfo svgInfo = svgEntryInfoList.at(jx);
++            if (!svgInfo.fileName().contains(prefix, Qt::CaseInsensitive)) continue;
++
++            QFile svgfile(svgInfo.absoluteFilePath());
++            QDomDocument svgDoc;
++            if (!svgDoc.setContent(&svgfile)) continue;
++
++            QList<QDomElement> elements;
++            QDomElement root = svgDoc.documentElement();
++            TextUtils::findElementsWithAttribute(root, "id", elements);
++            if (elements.count() < msi.connectorSvgIds.count()) continue;
++
++            QStringList ids;
++            foreach (QDomElement element, elements) {
++                ids << element.attribute("id");
++            }
++
++            bool allGood = true;
++            foreach (QString id, msi.connectorSvgIds) {
++                if (!ids.contains(id)) {
++                    allGood = false;
++                    break;
++                }
++            }
++
++            if (!allGood) continue;
++
++            QString destPath = copyToSvgFolder(svgInfo, false, PartFactory::folderPath(), "contrib");   // copy file with original name
++            if (!destPath.isEmpty()) {
++                QFileInfo destInfo(destPath);
++                QFile file(destPath);
++                DebugDialog::debug(QString("found missing %1").arg(destPath));
++                file.copy(destInfo.absoluteDir().absoluteFilePath(suffix));         // make another copy that has the name used in the fzp file
++                svgEntryInfoList.removeAt(jx);
++                break;
++            }
++        }
++    }
++
++    foreach (ModelPart * mp, missingModelParts) {
++		m_binManager->addToTempPartsBin(mp);
++        m_addedToTemp = true;
++    }
++
++	if (!m_addedToTemp) {
++		m_binManager->hideTempPartsBin();
++	}
++
++	// the bundled itself
++	this->mainLoad(sketchName, "");
++	setCurrentFile(fileName, addToRecent, setAsLastOpened);
++}
++
++bool MainWindow::copySvg(const QString & path, QFileInfoList & svgEntryInfoList) 
++{
++    int slash = path.indexOf("/");
++    QString subpath = path.mid(slash + 1);
++    bool gotOne = false;
++    for (int jx = svgEntryInfoList.count() - 1; jx >= 0; jx--) {
++        QFileInfo svgInfo = svgEntryInfoList.at(jx);
++        if (svgInfo.fileName().contains(subpath)) {
++            copyToSvgFolder(svgInfo, false, PartFactory::folderPath(), "contrib");
++            svgEntryInfoList.removeAt(jx);
++            // jrc 30 oct 2012: not sure why we can't just return at this point--can there be other matching files?
++            gotOne = true;
++        }
++    }
++
++    if (gotOne) return true;
++
++    // deal with a bug in which all the svg files exist in the fzz but the fz file points to the wrong name
++    // most of the time it's just a GUID difference
++
++    DebugDialog::debug(QString("svg matching fz path %1 not found").arg(path));
++    int guidix = GuidMatcher.lastIndexIn(subpath);
++    if (guidix < 0) return false;
++
++    QString originalGuid = GuidMatcher.cap(0);
++    QString tryPath = subpath;
++    tryPath.replace(guidix, originalGuid.length(), "%%%%");
++    for (int jx = svgEntryInfoList.count() - 1; jx >= 0; jx--) {
++        QFileInfo svgInfo = svgEntryInfoList.at(jx);
++        QString tempPath = svgInfo.fileName();
++        guidix = GuidMatcher.lastIndexIn(tempPath);
++        if (guidix < 0) continue;
++
++        tempPath.replace(guidix, GuidMatcher.cap(0).length(), "%%%%");
++        if (!tempPath.contains(tryPath)) continue;
++
++        QString destPath = copyToSvgFolder(svgInfo, false, PartFactory::folderPath(), "contrib");
++        if (!destPath.isEmpty()) {
++            QFile file(destPath);
++            guidix = GuidMatcher.lastIndexIn(destPath);
++            destPath.replace(guidix, GuidMatcher.cap(0).length(), originalGuid);
++            file.copy(destPath);
++            DebugDialog::debug(QString("found matching svg %1").arg(destPath));
++            svgEntryInfoList.removeAt(jx);
++            return true;
++        }
++    }
++
++    return false;
++
++}
++
++
++bool MainWindow::loadBundledNonAtomicEntity(const QString &fileName, Bundler* bundler, bool addToBin, bool dontAsk) {
++	QDir destFolder = QDir::temp();
++
++	FolderUtils::createFolderAnCdIntoIt(destFolder, TextUtils::getRandText());
++	QString unzipDirPath = destFolder.path();
++
++    QString error;
++	if(!FolderUtils::unzipTo(fileName, unzipDirPath, error)) {
++		QMessageBox::warning(
++			this,
++			tr("Fritzing"),
++			tr("Unable to open shareable '%1': %2").arg(fileName).arg(error)
++		);
++
++		// gotta return now, or loadBundledSketchAux will crash
++		return false;
++	}
++
++	QDir unzipDir(unzipDirPath);
++
++	if (bundler->preloadBundledAux(unzipDir, dontAsk)) {
++		QList<ModelPart*> mps = moveToPartsFolder(unzipDir,this,addToBin,true,FolderUtils::getUserDataStorePath("parts"), "contrib", false);
++		// the bundled itself
++		bundler->loadBundledAux(unzipDir,mps);
++	}
++
++	FolderUtils::rmdir(unzipDirPath);
++
++    return true;
++}
++
++/*
++void MainWindow::loadBundledPartFromWeb() {
++	QMainWindow *mw = new QMainWindow();
++	QString url = "http://localhost:8081/parts_gen/choose";
++	QWebView *view = new QWebView(mw);
++	mw->setCentralWidget(view);
++	view->setUrl(QUrl(url));
++	mw->show();
++	mw->raise();
++}
++*/
++
++ModelPart* MainWindow::loadBundledPart(const QString &fileName, bool addToBin) {
++	QDir destFolder = QDir::temp();
++
++	FolderUtils::createFolderAnCdIntoIt(destFolder, TextUtils::getRandText());
++	QString unzipDirPath = destFolder.path();
++
++    QString error;
++	if(!FolderUtils::unzipTo(fileName, unzipDirPath, error)) {
++		QMessageBox::warning(
++			this,
++			tr("Fritzing"),
++			tr("Unable to open shareable part '%1': %2").arg(fileName).arg(error)
++		);
++		return NULL;
++	}
++
++	QDir unzipDir(unzipDirPath);
++
++    QList<ModelPart*> mps;
++    try {
++	    mps = moveToPartsFolder(unzipDir, this, addToBin, true, FolderUtils::getUserDataStorePath("parts"), "user", true);
++    }
++    catch (const QString & msg) {
++		QMessageBox::warning(
++			this,
++			tr("Fritzing"),
++			msg
++		);
++        return NULL;
++    }
++
++	if (mps.count() != 1) {
++		// if this fails, that means that the bundled was wrong
++		QMessageBox::warning(
++			this,
++			tr("Fritzing"),
++			tr("Unable to load part from '%1'").arg(fileName)
++		);
++		return NULL;
++	}
++
++	FolderUtils::rmdir(unzipDirPath);
++
++	return mps[0];
++}
++
++void MainWindow::saveBundledPart(const QString &moduleId) {
++	QString modIdToExport;
++	ModelPart* mp;
++
++	if(moduleId.isEmpty()) {
++		if (m_currentGraphicsView == NULL) return;
++		PaletteItem *selectedPart = m_currentGraphicsView->getSelectedPart();
++		mp = selectedPart->modelPart();
++		modIdToExport = mp->moduleID();
++	} else {
++		modIdToExport = moduleId;
++		mp = m_referenceModel->retrieveModelPart(moduleId);
++	}
++	QString partTitle = mp->title();
++
++	QString fileExt;
++	QString path = defaultSaveFolder()+"/"+partTitle+FritzingBundledPartExtension;
++	QString bundledFileName = FolderUtils::getSaveFileName(
++			this,
++			tr("Specify a file name"),
++			path,
++			tr("Fritzing Part (*%1)").arg(FritzingBundledPartExtension),
++			&fileExt
++		  );
++
++	if (bundledFileName.isEmpty()) return; // Cancel pressed
++
++	if(!alreadyHasExtension(bundledFileName, FritzingBundledPartExtension)) {
++		bundledFileName += FritzingBundledPartExtension;
++	}
++
++	QDir destFolder = QDir::temp();
++
++	FolderUtils::createFolderAnCdIntoIt(destFolder, TextUtils::getRandText());
++	QString dirToRemove = destFolder.path();
++
++	QString aux = QFileInfo(bundledFileName).fileName();
++	QString destPartPath = // remove the last "z" from the extension
++			destFolder.path()+"/"+aux.left(aux.size()-1);
++	DebugDialog::debug("saving part temporarily to "+destPartPath);
++
++	//bool wasModified = isWindowModified();
++	//QString prevFileName = m_fileName;
++	//saveAsAux(destPartPath);
++	//m_fileName = prevFileName;
++	//setWindowModified(wasModified);
++	setTitle();
++
++	saveBundledAux(mp, destFolder);
++
++    QStringList skipSuffixes;
++	if(!FolderUtils::createZipAndSaveTo(destFolder, bundledFileName, skipSuffixes)) {
++		QMessageBox::warning(
++			this,
++			tr("Fritzing"),
++			tr("Unable to export %1 to shareable sketch").arg(bundledFileName)
++		);
++	}
++
++	FolderUtils::rmdir(dirToRemove);
++}
++
++QStringList MainWindow::saveBundledAux(ModelPart *mp, const QDir &destFolder) {
++	QStringList names;
++	QString partPath = mp->path();
++	QFile file(partPath);
++	QString fn = ZIP_PART + QFileInfo(partPath).fileName();
++	names << fn;
++	file.copy(destFolder.path()+"/"+fn);
++
++	QList<ViewLayer::ViewID> viewIDs;
++	viewIDs << ViewLayer::IconView << ViewLayer::BreadboardView << ViewLayer::SchematicView << ViewLayer::PCBView;
++	foreach (ViewLayer::ViewID viewID, viewIDs) {
++		QString basename = mp->hasBaseNameFor(viewID);
++		if (basename.isEmpty()) continue;
++
++		QString filename = PartFactory::getSvgFilename(mp, basename, true, true);
++		if (filename.isEmpty()) continue;
++
++		QFile file(filename);
++		basename.replace("/", ".");
++		QString fn = ZIP_SVG + basename;
++		names << fn;
++		file.copy(destFolder.path()+"/"+fn);
++	}
++
++	return names;
++}
++
++QList<ModelPart*> MainWindow::moveToPartsFolder(QDir &unzipDir, MainWindow* mw, bool addToBin, bool addToAlien, const QString & prefixFolder, const QString &destFolder, bool importingSinglePart) {
++	QStringList namefilters;
++	QList<ModelPart*> retval;
++
++	if (mw == NULL) {
++		throw tr("MainWindow::moveToPartsFolder mainwindow missing");
++	}
++
++    namefilters.clear();
++	namefilters << ZIP_PART+"*"; 
++    QList<QFileInfo> partEntryInfoList = unzipDir.entryInfoList(namefilters);
++
++    if (importingSinglePart && partEntryInfoList.count() > 0) {
++        // TODO use a stream reader
++        QFile file(partEntryInfoList[0].absoluteFilePath());
++        file.open(QFile::ReadOnly);
++        QString fzp = file.readAll();
++        file.close();
++        QString moduleID = TextUtils::parseForModuleID(fzp);
++        if (!moduleID.isEmpty() && m_referenceModel->retrieveModelPart(moduleID) != NULL) {
++            throw tr("There is already a part with id '%1' loaded into Fritzing.").arg(moduleID);
++        }
++    }
++
++
++	namefilters.clear();
++    namefilters << ZIP_SVG+"*";
++	foreach(QFileInfo file, unzipDir.entryInfoList(namefilters)) { // svg files
++		//DebugDialog::debug("unzip svg " + file.absoluteFilePath());
++		mw->copyToSvgFolder(file, addToAlien, prefixFolder, destFolder);
++	}
++
++
++	foreach(QFileInfo file, partEntryInfoList) { // part files
++		//DebugDialog::debug("unzip part " + file.absoluteFilePath());
++        ModelPart * mp = mw->copyToPartsFolder(file, addToAlien, prefixFolder, destFolder);
++		retval << mp;
++        if (addToBin) {
++            // should only be here when adding single new part
++		    m_binManager->addToMyParts(mp);
++	    }
++	}
++
++
++
++	return retval;
++}
++
++QString MainWindow::copyToSvgFolder(const QFileInfo& file, bool addToAlien, const QString & prefixFolder, const QString &destFolder) {
++	QFile svgfile(file.filePath());
++	// let's make sure that we remove just the suffix
++	QString fileName = file.fileName().remove(QRegExp("^"+ZIP_SVG));
++	QString viewFolder = fileName.left(fileName.indexOf("."));
++	fileName.remove(0, viewFolder.length() + 1);
++
++	QString destFilePath =
++		prefixFolder+"/svg/"+destFolder+"/"+viewFolder+"/"+fileName;
++
++	backupExistingFileIfExists(destFilePath);
++	if(svgfile.copy(destFilePath)) {
++		if (addToAlien) {
++			m_alienFiles << destFilePath;
++		}
++        return destFilePath;
++	}
++
++    return "";
++}
++
++ModelPart* MainWindow::copyToPartsFolder(const QFileInfo& file, bool addToAlien, const QString & prefixFolder, const QString &destFolder) {
++	QFile partfile(file.filePath());
++	// let's make sure that we remove just the suffix
++	QString destFilePath =
++		prefixFolder+"/"+destFolder+"/"+file.fileName().remove(QRegExp("^"+ZIP_PART));
++
++	backupExistingFileIfExists(destFilePath);
++	if(partfile.copy(destFilePath)) {
++		if (addToAlien) {
++			m_alienFiles << destFilePath;
++			m_alienPartsMsg = tr("Do you want to keep the imported parts?");
++		}
++	}
++	ModelPart *mp = m_referenceModel->loadPart(destFilePath, true);
++	mp->setAlien(true);
++
++	return mp;
++}
++
++void MainWindow::binSaved(bool hasPartsFromBundled) {
++	if(hasPartsFromBundled) {
++		// the bin will need those parts, so just keep them
++		m_alienFiles.clear();
++		resetTempFolder();
++	}
++}
++
++#undef ZIP_PART
++#undef ZIP_SVG
++
++
++void MainWindow::backupExistingFileIfExists(const QString &destFilePath) {
++	if(QFileInfo(destFilePath).exists()) {
++		if(m_tempDir.path() == ".") {
++			m_tempDir = QDir::temp();
++			FolderUtils::createFolderAnCdIntoIt(m_tempDir, TextUtils::getRandText());
++			DebugDialog::debug("debug folder for overwritten files: "+m_tempDir.path());
++		}
++
++		QString fileBackupName = QFileInfo(destFilePath).fileName();
++		m_filesReplacedByAlienOnes << destFilePath;
++		QFile file(destFilePath);
++		bool alreadyExists = file.exists();
++		file.copy(m_tempDir.path()+"/"+fileBackupName);
++
++		if(alreadyExists) {
++			file.remove(destFilePath);
++		}
++	}
++}
++
++void MainWindow::recoverBackupedFiles() {
++	foreach(QString originalFilePath, m_filesReplacedByAlienOnes) {
++		QFile file(m_tempDir.path()+"/"+QFileInfo(originalFilePath).fileName());
++		if(file.exists(originalFilePath)) {
++			file.remove();
++		}
++		file.copy(originalFilePath);
++	}
++	resetTempFolder();
++}
++
++void MainWindow::resetTempFolder() {
++	if(m_tempDir.path() != ".") {
++		FolderUtils::rmdir(m_tempDir);
++		m_tempDir = QDir::temp();
++	}
++	m_filesReplacedByAlienOnes.clear();
++}
++
++void MainWindow::routingStatusSlot(SketchWidget * sketchWidget, const RoutingStatus & routingStatus) {
++	m_routingStatus = routingStatus;
++	QString theText;
++	if (routingStatus.m_netCount == 0) {
++		theText = tr("No connections to route");
++	} else if (routingStatus.m_netCount == routingStatus.m_netRoutedCount) {
++		if (routingStatus.m_jumperItemCount == 0) {
++			theText = tr("Routing completed");
++		}
++		else {
++			theText = tr("Routing completed using %n jumper part(s)", "", routingStatus.m_jumperItemCount);
++		}
++	} else {
++		theText = tr("%1 of %2 nets routed - %n connector(s) still to be routed", "", routingStatus.m_connectorsLeftToRoute)
++			.arg(routingStatus.m_netRoutedCount)
++			.arg(routingStatus.m_netCount);
++	}
++
++	dynamic_cast<SketchAreaWidget *>(sketchWidget->parent())->routingStatusLabel()->setLabelText(theText);
++
++	updateTraceMenu();
++}
++
++void MainWindow::applyReadOnlyChange(bool isReadOnly) {
++	Q_UNUSED(isReadOnly);
++	//m_saveAct->setDisabled(isReadOnly);
++}
++
++void MainWindow::currentNavigatorChanged(MiniViewContainer * miniView)
++{
++	int index = m_navigators.indexOf(miniView);
++	if (index < 0) return;
++
++	int oldIndex = currentTabIndex();
++	if (oldIndex == index) return;
++
++	setCurrentTabIndex(index);
++}
++
++void MainWindow::viewSwitchedTo(int viewIndex) {
++	setCurrentTabIndex(viewIndex);
++}
++
++const QString MainWindow::fritzingTitle() {
++	if (m_currentGraphicsView == NULL) {
++		return FritzingWindow::fritzingTitle();
++	}
++
++	QString fritzing = FritzingWindow::fritzingTitle();
++	return tr("%1 - [%2]").arg(fritzing).arg(m_currentGraphicsView->viewName());
++}
++
++QAction *MainWindow::raiseWindowAction() {
++	return m_raiseWindowAct;
++}
++
++void MainWindow::raiseAndActivate() {
++	if(isMinimized()) {
++		showNormal();
++	}
++	raise();
++	QTimer::singleShot(20, this, SLOT(activateWindowAux()));
++}
++
++void MainWindow::activateWindowAux() {
++	activateWindow();
++}
++
++void MainWindow::updateRaiseWindowAction() {
++	QString actionText;
++	QFileInfo fileInfo(m_fwFilename);
++	if(fileInfo.exists()) {
++		int lastSlashIdx = m_fwFilename.lastIndexOf("/");
++		int beforeLastSlashIdx = m_fwFilename.left(lastSlashIdx).lastIndexOf("/");
++		actionText = beforeLastSlashIdx > -1 && lastSlashIdx > -1 ? "..." : "";
++		actionText += m_fwFilename.right(m_fwFilename.size()-beforeLastSlashIdx-1);
++	} else {
++		actionText = m_fwFilename;
++	}
++	m_raiseWindowAct->setText(actionText);
++	m_raiseWindowAct->setToolTip(m_fwFilename);
++	m_raiseWindowAct->setStatusTip("raise \""+m_fwFilename+"\" window");
++}
++
++QSizeGrip *MainWindow::sizeGrip() {
++	return m_sizeGrip;
++}
++
++QStatusBar *MainWindow::realStatusBar() {
++	return m_statusBar;
++}
++
++void MainWindow::moveEvent(QMoveEvent * event) {
++	FritzingWindow::moveEvent(event);
++	emit mainWindowMoved(this);
++}
++
++bool MainWindow::event(QEvent * e) {
++	switch (e->type()) {
++		case QEvent::WindowActivate:
++			emit changeActivationSignal(true, this);
++			break;
++		case QEvent::WindowDeactivate:
++			emit changeActivationSignal(false, this);
++			break;
++		default:
++			break;
++	}
++	return FritzingWindow::event(e);
++}
++
++void MainWindow::resizeEvent(QResizeEvent * event) {
++    if (m_sizeGrip) {
++	    m_sizeGrip->rearrange();
++    }
++	FritzingWindow::resizeEvent(event);
++}
++
++void MainWindow::showInViewHelp() {
++	//delete m_helper;
++	if (m_helper == NULL) {
++		m_helper = new Helper(this, true);
++		return;
++	}
++
++	bool toggle = !m_helper->helpVisible(currentTabIndex());
++	showAllFirstTimeHelp(toggle);
++
++	/*
++	m_helper->toggleHelpVisibility(currentTabIndex());
++	*/
++
++	m_showInViewHelpAct->setChecked(m_helper->helpVisible(currentTabIndex()));
++}
++
++
++void MainWindow::showAllFirstTimeHelp(bool show) {
++	if (m_helper) {
++		for (int i = 0; i < 3; i++) {
++			m_helper->setHelpVisibility(i, show);
++		}
++	}
++	m_showInViewHelpAct->setChecked(show);
++}
++
++void MainWindow::enableCheckUpdates(bool enabled)
++{
++	if (m_checkForUpdatesAct != NULL) {
++		m_checkForUpdatesAct->setEnabled(enabled);
++	}
++}
++
++
++void MainWindow::swapSelectedDelay(const QString & family, const QString & prop, QMap<QString, QString> & currPropsMap, ItemBase * itemBase) 
++{
++	m_swapTimer.stop();
++	m_swapTimer.setAll(family, prop, currPropsMap, itemBase);
++	m_swapTimer.start();
++}
++
++void MainWindow::swapSelectedTimeout()
++{
++	if (sender() == &m_swapTimer) {
++		QMap<QString, QString> map =  m_swapTimer.propsMap();
++		swapSelectedMap(m_swapTimer.family(), m_swapTimer.prop(), map, m_swapTimer.itemBase());
++	}
++}
++
++void MainWindow::swapSelectedMap(const QString & family, const QString & prop, QMap<QString, QString> & currPropsMap, ItemBase * itemBase) 
++{
++	if (itemBase == NULL) return;
++
++	QString generatedModuleID = currPropsMap.value("moduleID");
++
++	if (generatedModuleID.isEmpty()) {
++        if (prop.compare("layer") == 0) {
++	        if (family.compare("logo") == 0 || family.compare("pad") == 0 || family.contains("blocker", Qt::CaseInsensitive)) {
++		        QString value = Board::convertToXmlName(currPropsMap.value(prop));
++		        if (value.contains("copper1") && m_currentGraphicsView->boardLayers() == 1) {
++			        QMessageBox::warning(
++				        this,
++				        tr("No copper top layer"),
++				        tr("The copper top (copper 1) layer is not available on a one-sided board.  Please switch the board to double-sided or choose the copper bottom (copper 0) layer.")
++			        );
++			        return;
++		        }
++                // use the xml name
++                currPropsMap.insert(prop, value);
++	        }
++            else if (itemBase->itemType() == ModelPart::Wire) {
++                // assume this option is disabled for a one-sided board, so we would not get here?
++                m_pcbGraphicsView->changeTraceLayer(itemBase, false, NULL);
++                return;
++            }
++        }
++    }
++
++	if (generatedModuleID.isEmpty()) {
++		if (family.compare("Prototyping Board", Qt::CaseInsensitive) == 0) {
++			if (prop.compare("size", Qt::CaseInsensitive) == 0 || prop.compare("type", Qt::CaseInsensitive) == 0) {
++				QString size = currPropsMap.value("size");
++				QString type = currPropsMap.value("type");
++				if (type.compare("perfboard", Qt::CaseInsensitive) == 0) {
++					generatedModuleID = Perfboard::genModuleID(currPropsMap);
++				}
++				else if (type.compare("stripboard", Qt::CaseInsensitive) == 0) {
++					generatedModuleID = Stripboard::genModuleID(currPropsMap);
++				}
++			}
++		}
++	}
++
++    bool swapLayer = false;
++    ViewLayer::ViewLayerPlacement newViewLayerPlacement = ViewLayer::UnknownPlacement;
++    if (prop.compare("layer") == 0) {
++        if (itemBase->modelPart()->flippedSMD() || itemBase->itemType() == ModelPart::Part) {
++            ItemBase * viewItem = itemBase->modelPart()->viewItem(ViewLayer::PCBView);
++            if (viewItem) {
++                ViewLayer::ViewLayerPlacement vlp = (currPropsMap.value(prop) == ItemBase::TranslatedPropertyNames.value("bottom") ? ViewLayer::NewBottom : ViewLayer::NewTop);
++                if (viewItem->viewLayerPlacement() != newViewLayerPlacement) {
++                    swapLayer = true;
++                    newViewLayerPlacement = vlp;
++                }
++            }
++        }
++    }
++
++	if (!generatedModuleID.isEmpty()) {
++		ModelPart * modelPart = m_referenceModel->retrieveModelPart(generatedModuleID);
++		if (modelPart == NULL) {
++			if (!m_referenceModel->genFZP(generatedModuleID, m_referenceModel)) {
++				return;
++			}
++		}
++
++		swapSelectedAux(itemBase->layerKinChief(), generatedModuleID, swapLayer, newViewLayerPlacement, currPropsMap);
++		return;
++	}
++
++    if (swapLayer) {
++        swapSelectedAux(itemBase->layerKinChief(), itemBase->moduleID(), true, newViewLayerPlacement, currPropsMap);
++        return;
++    }
++
++	if ((prop.compare("package", Qt::CaseSensitive) != 0) && swapSpecial(prop, currPropsMap)) {
++		return;
++	}
++
++	foreach (QString key, currPropsMap.keys()) {
++		QString value = currPropsMap.value(key);
++		m_referenceModel->recordProperty(key, value);
++	}
++
++	QString moduleID = m_referenceModel->retrieveModuleIdWith(family, prop, true);
++	bool exactMatch = m_referenceModel->lastWasExactMatch();
++
++	if (moduleID.isEmpty()) {
++		QMessageBox::information(
++			this,
++			tr("Sorry!"),
++			tr(
++			 "No part with those characteristics.\n"
++			 "We're working to avoid this message, and only let you choose between properties that do exist")
++		);
++		return;
++	}
++
++
++
++	itemBase = itemBase->layerKinChief();
++
++	if(!exactMatch) {
++		AutoCloseMessageBox::showMessage(this, tr("No exactly matching part found; Fritzing chose the closest match."));
++	}
++
++	swapSelectedAux(itemBase, moduleID, false, ViewLayer::UnknownPlacement, currPropsMap);
++}
++
++bool MainWindow::swapSpecial(const QString & theProp, QMap<QString, QString> & currPropsMap) {
++	ItemBase * itemBase = m_infoView->currentItem();
++	QString pinSpacing, resistance;
++    int layers = 0;
++
++	foreach (QString key, currPropsMap.keys()) {
++		if (key.compare("layers", Qt::CaseInsensitive) == 0) {
++			if (!Board::isBoard(itemBase)) continue;
++
++			QString value = currPropsMap.value(key, "");
++			if (value.compare(Board::OneLayerTranslated) == 0) {
++				layers = 1;
++			}
++			else if (value.compare(Board::TwoLayersTranslated) == 0) {
++				layers = 2;
++			}
++        }
++
++		if (key.compare("resistance", Qt::CaseInsensitive) == 0) {
++			resistance = currPropsMap.value(key);
++			continue;
++		}
++		if (key.compare("pin spacing", Qt::CaseInsensitive) == 0) {
++			pinSpacing = currPropsMap.value(key);
++			continue;
++		}
++	}
++
++    if (layers != 0) {
++        currPropsMap.insert("layers", QString::number(layers));
++        if (theProp.compare("layers") == 0) {
++            QString msg = (layers == 1) ? tr("Change to single layer pcb") : tr("Change to two layer pcb");
++            swapLayers(itemBase, layers, msg, SketchWidget::PropChangeDelay);
++            return true;
++        }
++	}
++
++	if (!resistance.isEmpty() || !pinSpacing.isEmpty()) {
++		if (theProp.contains("band", Qt::CaseInsensitive)) {
++			// swap 4band for 5band or vice versa.
++			return false;
++		}
++
++		Resistor * resistor = qobject_cast<Resistor *>(itemBase);
++		if (resistor != NULL) {
++			m_currentGraphicsView->setResistance(resistance, pinSpacing);
++			return true;
++		}
++	}
++
++	return false;
++}
++
++void MainWindow::swapLayers(ItemBase * itemBase, int layers, const QString & msg, int delay) {
++    QUndoCommand* parentCommand = new QUndoCommand(msg);
++	new CleanUpWiresCommand(m_breadboardGraphicsView, CleanUpWiresCommand::UndoOnly, parentCommand);
++	new CleanUpRatsnestsCommand(m_breadboardGraphicsView, CleanUpWiresCommand::UndoOnly, parentCommand);
++    m_pcbGraphicsView->swapLayers(itemBase, layers, parentCommand);
++	// need to defer execution so the content of the info view doesn't change during an event that started in the info view
++	m_undoStack->waitPush(parentCommand, delay);
++}
++
++void MainWindow::swapSelectedAux(ItemBase * itemBase, const QString & moduleID, bool useViewLayerPlacement, ViewLayer::ViewLayerPlacement overrideViewLayerPlacement,  QMap<QString, QString> & propsMap) {
++
++	QUndoCommand* parentCommand = new QUndoCommand(tr("Swapped %1 with module %2").arg(itemBase->instanceTitle()).arg(moduleID));
++	new CleanUpWiresCommand(m_breadboardGraphicsView, CleanUpWiresCommand::UndoOnly, parentCommand);
++	new CleanUpRatsnestsCommand(m_breadboardGraphicsView, CleanUpWiresCommand::UndoOnly, parentCommand);
++
++    ViewLayer::ViewLayerPlacement viewLayerPlacement = itemBase->viewLayerPlacement();
++    ModelPart * modelPart = m_referenceModel->retrieveModelPart(moduleID);
++    if (m_pcbGraphicsView->boardLayers() == 2) {
++        if (modelPart->flippedSMD()) {
++            //viewLayerPlacement = m_pcbGraphicsView->dropOnBottom() ? ViewLayer::NewBottom : ViewLayer::NewTop;
++            if (useViewLayerPlacement) viewLayerPlacement = overrideViewLayerPlacement;
++        }
++        else if (modelPart->itemType() == ModelPart::Part) {
++            //viewLayerPlacement = m_pcbGraphicsView->dropOnBottom() ? ViewLayer::NewBottom : ViewLayer::NewTop;
++            if (useViewLayerPlacement) viewLayerPlacement = overrideViewLayerPlacement;
++        }
++    }
++    else {
++        if (modelPart->flippedSMD()) {
++            viewLayerPlacement = ViewLayer::NewBottom;
++        }
++        else if (modelPart->itemType() == ModelPart::Part) {
++            //viewLayerPlacement = m_pcbGraphicsView->dropOnBottom() ? ViewLayer::NewBottom : ViewLayer::NewTop;
++            if (useViewLayerPlacement) viewLayerPlacement = overrideViewLayerPlacement;
++        }
++    }
++
++	swapSelectedAuxAux(itemBase, moduleID, viewLayerPlacement, propsMap, parentCommand);
++    
++	// need to defer execution so the content of the info view doesn't change during an event that started in the info view
++	m_undoStack->waitPush(parentCommand, SketchWidget::PropChangeDelay);
++
++}
++
++void MainWindow::swapBoardImageSlot(SketchWidget * sketchWidget, ItemBase * itemBase, const QString & filename, const QString & moduleID, bool addName) {
++
++	QUndoCommand* parentCommand = new QUndoCommand(tr("Change image to %2").arg(filename));
++    QMap<QString, QString> propsMap;
++	long newID = swapSelectedAuxAux(itemBase, moduleID, itemBase->viewLayerPlacement(), propsMap, parentCommand);
++
++    LoadLogoImageCommand * cmd = new LoadLogoImageCommand(sketchWidget, newID, "", QSizeF(0,0), filename, filename, addName, parentCommand);
++    cmd->setRedoOnly();
++   
++	// need to defer execution so the content of the info view doesn't change during an event that started in the info view
++	m_undoStack->waitPush(parentCommand, SketchWidget::PropChangeDelay);
++}
++
++
++void MainWindow::subSwapSlot(SketchWidget * sketchWidget, ItemBase * itemBase, const QString & newModuleID, ViewLayer::ViewLayerPlacement viewLayerPlacement, long & newID, QUndoCommand * parentCommand) {
++	Q_UNUSED(sketchWidget);
++    QMap<QString, QString> propsMap;
++	newID = swapSelectedAuxAux(itemBase, newModuleID, viewLayerPlacement, propsMap, parentCommand);
++}
++
++long MainWindow::swapSelectedAuxAux(ItemBase * itemBase, const QString & moduleID,  ViewLayer::ViewLayerPlacement viewLayerPlacement, QMap<QString, QString> & propsMap, QUndoCommand * parentCommand) 
++{
++	long modelIndex = ModelPart::nextIndex();
++
++	QList<SketchWidget *> sketchWidgets;
++
++    // master view must go last, since it creates the delete command, and possibly has all the local props
++    switch (itemBase->viewID()) {
++        case ViewLayer::SchematicView:
++		    sketchWidgets << m_pcbGraphicsView << m_breadboardGraphicsView << m_schematicGraphicsView;
++            break;
++        case ViewLayer::PCBView:
++            sketchWidgets << m_schematicGraphicsView << m_breadboardGraphicsView << m_pcbGraphicsView;
++            break;
++        default:
++            sketchWidgets << m_schematicGraphicsView << m_pcbGraphicsView << m_breadboardGraphicsView;
++            break;
++	}
++
++    SwapThing swapThing;
++    swapThing.firstTime = true;
++    swapThing.itemBase = itemBase;
++    swapThing.newModelIndex = modelIndex;
++    swapThing.newModuleID = moduleID;
++    swapThing.viewLayerPlacement = viewLayerPlacement;
++    swapThing.parentCommand = parentCommand;
++    swapThing.propsMap = propsMap;
++
++    long newID = 0;
++    for (int i = 0; i < 3; i++) {
++        long tempID = sketchWidgets[i]->setUpSwap(swapThing, i == 2);
++        if (newID == 0 && tempID != 0) newID = tempID;
++    }
++
++	// TODO:  z-order?
++
++	return newID;
++}
++
++void MainWindow::svgMissingLayer(const QString & layername, const QString & path) {
++	QMessageBox::warning(
++		this,
++		tr("Fritzing"),
++		tr("Svg %1 is missing a '%2' layer. "
++			"For more information on how to create a custom board shape, "
++			"see the tutorial at <a href='http://fritzing.org/learning/tutorials/designing-pcb/pcb-custom-shape/'>http://fritzing.org/learning/tutorials/designing-pcb/pcb-custom-shape/</a>.")
++		.arg(path)
++		.arg(layername)
++	);
++}
++
++void MainWindow::addDefaultParts() {
++	if (m_pcbGraphicsView == NULL) return;
++
++	m_pcbGraphicsView->addDefaultParts();
++	m_breadboardGraphicsView->addDefaultParts();
++	m_schematicGraphicsView->addDefaultParts();
++}
++
++MainWindow * MainWindow::newMainWindow(ReferenceModel *referenceModel, const QString & displayPath, bool showProgress, bool lockFiles) {
++    MainWindow * mw = new MainWindow(referenceModel, NULL);
++	if (showProgress) {
++		mw->showFileProgressDialog(displayPath);
++	}
++
++    mw->init(referenceModel, lockFiles);
++
++	return mw;
++}
++
++void  MainWindow::clearFileProgressDialog() {
++	if (m_fileProgressDialog) {
++		m_fileProgressDialog->close();
++		delete m_fileProgressDialog;
++		m_fileProgressDialog = NULL;
++	}
++}
++
++void MainWindow::setFileProgressPath(const QString & path)
++{
++	if (m_fileProgressDialog) m_fileProgressDialog->setMessage(tr("loading %1").arg(path));
++}
++
++FileProgressDialog * MainWindow::fileProgressDialog()
++{
++	return m_fileProgressDialog;
++}
++
++void MainWindow::showFileProgressDialog(const QString & path) {
++    m_fileProgressDialog = new FileProgressDialog(tr("Loading..."), 200, this);
++	m_fileProgressDialog->setBinLoadingChunk(50);
++	if (!path.isEmpty()) {
++		setFileProgressPath(QFileInfo(path).fileName());
++	}
++	else {
++		setFileProgressPath(tr("new sketch"));
++	}
++}
++
++const QString &MainWindow::selectedModuleID() {
++	if(m_currentGraphicsView) {
++		return m_currentGraphicsView->selectedModuleID();
++	} else {
++		return ___emptyString___;
++	}
++}
++
++void MainWindow::redrawSketch() {
++    QList<ConnectorItem *> visited;
++	foreach (QGraphicsItem * item, m_currentGraphicsView->scene()->items()) {
++		item->update();
++		ConnectorItem * c = dynamic_cast<ConnectorItem *>(item);
++		if (c != NULL) {
++			c->restoreColor(visited);
++		}
++	}
++}
++
++void MainWindow::statusMessage(QString message, int timeout) {
++	QStatusBar * sb = realStatusBar();
++	if (sb != NULL) {
++		sb->showMessage(message, timeout);
++	}
++}
++
++void MainWindow::dropPaste(SketchWidget * sketchWidget) {
++	Q_UNUSED(sketchWidget);
++	pasteInPlace();
++}
++
++void MainWindow::updateLayerMenuSlot() {
++	updateLayerMenu(true);
++}
++
++bool MainWindow::save() {
++	bool result = FritzingWindow::save();
++	if (result) {
++		QSettings settings;
++		settings.setValue("lastOpenSketch", m_fwFilename);
++	}
++	return result;
++}
++
++bool MainWindow::saveAs() {
++	bool result = false;
++	if (m_fwFilename.endsWith(FritzingSketchExtension)) {
++		result = FritzingWindow::saveAs(m_fwFilename + 'z', false);
++	}
++	else {
++		result = FritzingWindow::saveAs();
++	}
++	if (result) {
++		QSettings settings;
++		settings.setValue("lastOpenSketch", m_fwFilename);
++	}
++	return result;
++}
++
++void MainWindow::changeBoardLayers(int layers, bool doEmit) {
++	Q_UNUSED(doEmit);
++	Q_UNUSED(layers);
++	updateActiveLayerButtons();
++	m_currentGraphicsView->updateConnectors();
++}
++
++void MainWindow::updateActiveLayerButtons() {
++    if (m_activeLayerButtonWidget != NULL) {
++	    int index = activeLayerIndex();
++	    bool enabled = index >= 0;
++
++	    m_activeLayerButtonWidget->setCurrentIndex(index);
++	    m_activeLayerButtonWidget->setVisible(enabled);
++
++	    m_activeLayerBothAct->setEnabled(enabled);
++	    m_activeLayerBottomAct->setEnabled(enabled);
++	    m_activeLayerTopAct->setEnabled(enabled);
++
++	    QList<QAction *> actions;
++	    actions << m_activeLayerBothAct << m_activeLayerBottomAct << m_activeLayerTopAct;
++	    setActionsIcons(index, actions);
++    }
++
++    if (m_viewFromButtonWidget != NULL) {
++        if (m_pcbGraphicsView) {
++            bool viewFromBelow = m_pcbGraphicsView->viewFromBelow();
++            int index = (viewFromBelow ? 1 : 0);
++	        m_viewFromButtonWidget->setCurrentIndex(index);
++	        m_viewFromButtonWidget->setVisible(true);
++            m_viewFromBelowToggleAct->setChecked(viewFromBelow);
++
++	        m_viewFromBelowToggleAct->setEnabled(true);
++	        m_viewFromBelowAct->setEnabled(true);
++	        m_viewFromAboveAct->setEnabled(true);
++        }
++    }
++}
++
++int MainWindow::activeLayerIndex() 
++{
++	if (m_currentGraphicsView == NULL) return -1;
++
++	if (m_currentGraphicsView->boardLayers() == 2 || activeLayerWidgetAlwaysOn()) {
++		bool copper0Visible = m_currentGraphicsView->layerIsActive(ViewLayer::Copper0);
++		bool copper1Visible = m_currentGraphicsView->layerIsActive(ViewLayer::Copper1);
++		if (copper0Visible && copper1Visible) {
++			return 0;
++		}
++		else if (copper1Visible) {
++			return 2;
++		}
++		else if (copper0Visible) {
++			return 1;
++		}
++	}
++
++	return -1;
++}
++
++bool MainWindow::activeLayerWidgetAlwaysOn() {
++	return false;
++}
++
++/**
++ * A slot for saving a copy of the current sketch to a temp location.
++ * This should be called every X minutes as well as just before certain
++ * events, such as saves, part imports, file export/printing. This relies
++ * on the m_autosaveNeeded variable and the undoStack being dirty for
++ * an autosave to be attempted.
++ */
++void  MainWindow::backupSketch() {
++	if (ProcessEventBlocker::isProcessing()) {
++		// don't want to autosave during autorouting, for example
++		return;
++	}
++
++    if (m_autosaveNeeded && !m_undoStack->isClean()) {
++        m_autosaveNeeded = false;			// clear this now in case the save takes a really long time
++
++        DebugDialog::debug(QString("%1 autosaved as %2").arg(m_fwFilename).arg(m_backupFileNameAndPath));
++        statusBar()->showMessage(tr("Backing up '%1'").arg(m_fwFilename), 2000);
++		ProcessEventBlocker::processEvents();
++		m_backingUp = true;
++		connectStartSave(true);
++		m_sketchModel->save(m_backupFileNameAndPath, false);
++		connectStartSave(false);
++		m_backingUp = false;
++    }
++}
++
++/**
++ * This function is used to trigger an autosave at the next autosave
++ * timer event. It is connected to the QUndoStack::indexChanged(int)
++ * signal so that any change to the undo stack triggers autosaves.
++ * This function can be called independent of this signal and
++ * still work properly.
++ */
++void MainWindow::autosaveNeeded(int index) {
++    Q_UNUSED(index);
++    //DebugDialog::debug(QString("Triggering autosave"));
++    m_autosaveNeeded = true;
++}
++
++/**
++ * delete the backup file when the undostack is clean.
++ */
++void MainWindow::undoStackCleanChanged(bool isClean) {
++    // DebugDialog::debug(QString("Clean status changed to %1").arg(isClean));
++    if (isClean) {
++        QFile::remove(m_backupFileNameAndPath);
++    }
++}
++
++void MainWindow::setAutosavePeriod(int minutes) {
++	setAutosave(minutes, AutosaveEnabled);
++}
++
++void MainWindow::setAutosaveEnabled(bool enabled) {
++	setAutosave(AutosaveTimeoutMinutes, enabled);
++}
++
++void MainWindow::setAutosave(int minutes, bool enabled) {
++	AutosaveTimeoutMinutes = minutes;
++	AutosaveEnabled = enabled;
++	foreach (QWidget * widget, QApplication::topLevelWidgets()) {
++		MainWindow * mainWindow = qobject_cast<MainWindow *>(widget);
++		if (mainWindow == NULL) continue;
++
++		mainWindow->m_autosaveTimer.stop();
++		if (qobject_cast<PEMainWindow *>(widget)) {
++			continue;
++		}
++
++		if (AutosaveEnabled) {
++			// is there a way to get the current timer offset so that all the timers aren't running in sync?
++			// or just add some random time...
++			mainWindow->m_autosaveTimer.start(AutosaveTimeoutMinutes * 60 * 1000);
++		}
++	}
++}
++
++bool MainWindow::hasLinkedProgramFiles(const QString & filename, QStringList & linkedProgramFiles) 
++{
++	QFile file(filename);
++	file.open(QFile::ReadOnly);
++	QXmlStreamReader xml(&file);
++    xml.setNamespaceProcessing(false);
++
++	bool done = false;
++	while (!xml.atEnd()) {
++        switch (xml.readNext()) {
++        case QXmlStreamReader::StartElement:
++			if (xml.name().toString().compare("program") == 0) {
++				linkedProgramFiles.append(xml.readElementText());
++				break;
++			}
++			if (xml.name().toString().compare("views") == 0) {
++				done = true;
++				break;
++			}
++			if (xml.name().toString().compare("instances") == 0) {
++				done = true;
++				break;
++			}
++		default:
++			break;
++		}
++
++		if (done) break;
++	}
++
++	return linkedProgramFiles.count() > 0;
++}
++
++QString MainWindow::getExtensionString() {
++	return tr("Fritzing (*%1)").arg(fileExtension());
++}
++
++QStringList MainWindow::getExtensions() {
++	QStringList extensions;
++	extensions.append(fileExtension());
++	return extensions;
++}
++
++void MainWindow::firstTimeHelpHidden() {
++	m_showInViewHelpAct->setChecked(false);
++}
++
++void MainWindow::routingStatusLabelMousePress(QMouseEvent* event) {
++	routingStatusLabelMouse(event, true);
++}
++
++void MainWindow::routingStatusLabelMouseRelease(QMouseEvent* event) {
++	routingStatusLabelMouse(event, false);
++}
++
++void MainWindow::routingStatusLabelMouse(QMouseEvent*, bool show) {
++	if (show) DebugDialog::debug("-------");
++
++	QSet<ConnectorItem *> toShow;
++	foreach (QGraphicsItem * item, m_currentGraphicsView->scene()->items()) {
++		VirtualWire * vw = dynamic_cast<VirtualWire *>(item);
++		if (vw == NULL) continue;
++
++		foreach (ConnectorItem * connectorItem, vw->connector0()->connectedToItems()) {
++			toShow.insert(connectorItem);
++		}
++		foreach (ConnectorItem * connectorItem, vw->connector1()->connectedToItems()) {
++			toShow.insert(connectorItem);
++		}
++	}
++	QList<ConnectorItem *> visited;
++	foreach (ConnectorItem * connectorItem, toShow) {
++		if (show) {
++			DebugDialog::debug(QString("unrouted %1 %2 %3 %4")
++				.arg(connectorItem->attachedToInstanceTitle())
++				.arg(connectorItem->attachedToID())
++				.arg(connectorItem->attachedTo()->title())
++				.arg(connectorItem->connectorSharedName()));
++		}
++
++		if (connectorItem->isActive() && connectorItem->isVisible() && !connectorItem->hidden() && !connectorItem->layerHidden()) {
++			connectorItem->showEqualPotential(show, visited);
++		}
++		else {
++			connectorItem = connectorItem->getCrossLayerConnectorItem();
++			if (connectorItem) connectorItem->showEqualPotential(show, visited);
++		}
++	}
++
++    if (!show && toShow.count() == 0) {
++            QMessageBox::information(this, tr("Unrouted connections"), 
++            tr("There are no unrouted connections in this view."));
++    }
++}
++
++void MainWindow::setReportMissingModules(bool b) {
++	if (m_sketchModel) {
++		m_sketchModel->setReportMissingModules(b);
++	}
++}
++
++void MainWindow::boardDeletedSlot() 
++{
++	activeLayerBottom();
++}
++
++void MainWindow::cursorLocationSlot(double xinches, double yinches)
++{
++	if (m_locationLabel) {
++		QString units;
++		double x, y;
++
++		m_locationLabel->setProperty("location", QSizeF(xinches, xinches));
++
++		if (m_locationLabelUnits.compare("mm") == 0) {
++			units = "mm";
++			x = xinches * 25.4;
++			y = yinches * 25.4;
++		}
++		else if (m_locationLabelUnits.compare("px") == 0) {
++			units = "px";
++			x = xinches * GraphicsUtils::SVGDPI;
++			y = yinches * GraphicsUtils::SVGDPI;
++		}
++		else {
++			units = "in";
++			x = xinches;
++			y = yinches;
++		}
++
++		m_locationLabel->setText(tr("%1 %2 %3")
++			.arg(x, 0, 'f', 3)
++			.arg(y, 0, 'f', 3)
++			.arg(units) );
++	}
++}
++
++void MainWindow::locationLabelClicked()
++{
++	if (m_locationLabelUnits.compare("mm") == 0) {
++		m_locationLabelUnits = "px";
++	}
++	else if (m_locationLabelUnits.compare("px") == 0) {
++		m_locationLabelUnits = "in";
++	}
++	else if (m_locationLabelUnits.compare("in") == 0) {
++		m_locationLabelUnits = "mm";
++	}
++	else {
++		m_locationLabelUnits = "in";
++	}
++
++	if (m_locationLabel) {
++		QVariant variant =  m_locationLabel->property("location");
++		if (variant.isValid()) {
++			QSizeF size = variant.toSizeF();
++			cursorLocationSlot(size.width(), size.height());
++		}
++		else {
++			cursorLocationSlot(0, 0);
++		}
++	}
++		
++	QSettings settings;
++	settings.setValue("LocationInches", QVariant(m_locationLabelUnits));
++}
++
++void MainWindow::filenameIfSlot(QString & filename)
++{
++	filename = QFileInfo(fileName()).fileName();
++}
++
++QList<SketchWidget *> MainWindow::sketchWidgets() 
++{
++	QList<SketchWidget *> list;
++	list << m_breadboardGraphicsView << m_schematicGraphicsView << m_pcbGraphicsView;
++	return list;
++}
++
++void MainWindow::setCloseSilently(bool cs)
++{
++	m_closeSilently = cs;
++}
++
++PCBSketchWidget * MainWindow::pcbView() {
++	return m_pcbGraphicsView;
++}
++
++void MainWindow::noBackup()
++{
++	m_autosaveTimer.stop();
++}
++
++void MainWindow::hideTempPartsBin() {
++	if (m_binManager) m_binManager->hideTempPartsBin();
++}
++
++void MainWindow::setActiveWire(Wire * wire) {
++	m_activeWire = wire;
++}
++
++void MainWindow::setActiveConnectorItem(ConnectorItem * connectorItem) {
++	m_activeConnectorItem = connectorItem;
++}
++
++const QString & MainWindow::fritzingVersion() {
++	if (m_sketchModel) return m_sketchModel->fritzingVersion();
++
++	return ___emptyString___;
++}
++
++
++void MainWindow::dragEnterEvent(QDragEnterEvent *event)
++{
++    const QMimeData* mimeData = event->mimeData();
++ 
++    if (mimeData->hasUrls()) {
++        QStringList pathList;
++        QList<QUrl> urlList = mimeData->urls();
++ 
++        // extract the local paths of the files
++        for (int i = 0; i < urlList.size() && i < 32; ++i) {
++            QString fn = urlList.at(i).toLocalFile();
++            foreach (QString ext, fritzingExtensions()) {
++                if (fn.endsWith(ext)) {
++                    event->acceptProposedAction();
++                    return;
++                }
++            }
++        }
++    }
++}
++
++void MainWindow::dropEvent(QDropEvent *event)
++{
++    const QMimeData* mimeData = event->mimeData();
++ 
++    if (mimeData->hasUrls()) {
++        QStringList pathList;
++        QList<QUrl> urlList = mimeData->urls();
++ 
++        // extract the local paths of the files
++        for (int i = 0; i < urlList.size() && i < 32; ++i) {
++            mainLoadAux(urlList.at(i).toLocalFile());
++        }
++    }
++}
++
++bool MainWindow::hasAnyAlien() {
++    return m_addedToTemp;
++}
++
++void MainWindow::initStyleSheet() 
++{
++    QString suffix = getStyleSheetSuffix();
++	QFile styleSheet(QString(":/resources/styles/%1.qss").arg(suffix));
++    if (!styleSheet.open(QIODevice::ReadOnly)) {
++		DebugDialog::debug(QString("Unable to open :/resources/styles/%1.qss").arg(suffix));
++	} else {
++		QString platformDependantStyle = "";
++		QString platformDependantStylePath;
++#ifdef Q_WS_X11
++		if(style()->metaObject()->className()==QString("OxygenStyle")) {
++			QFile oxygenStyleSheet(QString(":/resources/styles/linux-kde-oxygen-%1.qss").arg(suffix));
++			if(oxygenStyleSheet.open(QIODevice::ReadOnly)) {
++				platformDependantStyle += oxygenStyleSheet.readAll();
++			}
++		}
++		platformDependantStylePath = QString(":/resources/styles/linux-%1.qss").arg(suffix);
++#endif
++
++#ifdef Q_WS_MAC
++		platformDependantStylePath = QString(":/resources/styles/mac-%1.qss").arg(suffix);
++#endif
++
++#ifdef Q_WS_WIN
++		platformDependantStylePath = QString(":/resources/styles/win-%1.qss").arg(suffix);
++#endif
++
++		QFile platformDependantStyleSheet(platformDependantStylePath);
++		if(platformDependantStyleSheet.open(QIODevice::ReadOnly)) {
++			platformDependantStyle += platformDependantStyleSheet.readAll();
++		}
++		setStyleSheet(styleSheet.readAll()+platformDependantStyle);
++	}
++}
++
++QString MainWindow::getStyleSheetSuffix() {
++    return "fritzing";
++}
++
++void MainWindow::addToMyParts(ModelPart * modelPart)
++{
++    if (modelPart != NULL) m_binManager->addToMyParts(modelPart);
++}
++
++bool MainWindow::anyUsePart(const QString & moduleID) {
++    foreach (QWidget *widget, QApplication::topLevelWidgets()) {
++        MainWindow *mainWindow = qobject_cast<MainWindow *>(widget);
++		if (mainWindow == NULL) continue;
++			    
++        if (mainWindow->usesPart(moduleID)) {
++            return true;
++        }
++    }
++
++    return false;
++}
++
++bool MainWindow::usesPart(const QString & moduleID) {
++    if (m_currentGraphicsView == NULL) return false;
++
++    foreach (QGraphicsItem * item, m_currentGraphicsView->scene()->items()) {
++        ItemBase * itemBase = dynamic_cast<ItemBase *>(item);
++        if (itemBase != NULL && itemBase->moduleID().compare(moduleID) == 0) {
++            return true;
++        }
++    }
++
++    return false;
++}
++
++bool MainWindow::updateParts(const QString & moduleID, QUndoCommand * parentCommand) {
++    if (m_currentGraphicsView == NULL) return false;
++
++    QSet<ItemBase *> itemBases;
++    foreach (QGraphicsItem * item, m_currentGraphicsView->scene()->items()) {
++        ItemBase * itemBase = dynamic_cast<ItemBase *>(item);
++        if (itemBase == NULL) continue;       
++        if (itemBase->moduleID().compare(moduleID) != 0) continue;
++
++        itemBases.insert(itemBase->layerKinChief());
++    }
++
++    QMap<QString, QString> propsMap;
++    foreach (ItemBase * itemBase, itemBases) {
++        swapSelectedAuxAux(itemBase, moduleID, itemBase->viewLayerPlacement(), propsMap, parentCommand);
++    }
++
++    return true;
++}
++
++void MainWindow::showStatusMessage(const QString & message)
++{
++    if (sender() == m_statusBar) {
++        return;
++    }
++
++    if (message == m_statusBar->currentMessage()) {
++        return;
++    }
++
++    //DebugDialog::debug("show message " + message);
++    m_statusBar->blockSignals(true);
++    m_statusBar->showMessage(message);
++    m_statusBar->blockSignals(false);
++}
++
++void MainWindow::updatePartsBin(const QString & moduleID) {
++	m_binManager->reloadPart(moduleID);
++}
++
++bool MainWindow::hasCustomBoardShape() {
++	if (m_pcbGraphicsView == NULL) return false;
++
++	return m_pcbGraphicsView->hasCustomBoardShape();
++}
++
++void MainWindow::selectPartsWithModuleID(ModelPart * modelPart) {
++    if (m_currentGraphicsView == NULL) return;
++
++    m_currentGraphicsView->selectItemsWithModuleID(modelPart);
++}
++
++void MainWindow::addToSketch(QList<ModelPart *> & modelParts) {
++    if (m_currentGraphicsView == NULL) return;
++
++    m_currentGraphicsView->addToSketch(modelParts);
++}
++
++void MainWindow::initProgrammingWidget() {
++    return; // not yet implemented
++
++    m_programView = new ProgramWindow(this);
++
++	connect(m_programView, SIGNAL(linkToProgramFile(const QString &, const QString &, const QString &, bool, bool)), 
++			this, SLOT(linkToProgramFile(const QString &, const QString &, const QString &, bool, bool)));
++
++	m_programView->setup();
++
++	SketchAreaWidget * sketchAreaWidget = new SketchAreaWidget(m_programView, this);
++	addTab(sketchAreaWidget, tr("Code"));
++}
++
++void MainWindow::orderFabHoverEnter() {
++    if (!QuoteDialog::quoteSucceeded()) return;
++    if (m_rolloverQuoteDialog && m_rolloverQuoteDialog->isVisible()) return;
++
++    QTimer::singleShot(1, this, SLOT(fireQuote()));
++}
++
++void MainWindow::fireQuote() {
++    if (!QuoteDialog::quoteSucceeded()) return;
++
++    m_rolloverQuoteDialog = m_pcbGraphicsView->quoteDialog(m_pcbWidget);
++    if (m_rolloverQuoteDialog == NULL) return;
++
++    //DebugDialog::debug("enter fab button");
++    //QWidget * toolbar = m_pcbWidget->toolbar();
++    //QRect r = toolbar->geometry();
++    //QPointF p = toolbar->parentWidget()->mapToGlobal(r.topLeft());
++
++	Qt::WindowFlags flags = m_rolloverQuoteDialog->windowFlags();
++    flags = Qt::Window | Qt::Dialog | Qt::FramelessWindowHint;
++	m_rolloverQuoteDialog->setWindowFlags(flags);
++    m_rolloverQuoteDialog->show();
++
++    // seems to require setting position after show()
++
++    QRect t = m_pcbWidget->toolbar()->geometry();
++    QPoint gt = m_pcbWidget->toolbar()->parentWidget()->mapToGlobal(t.topLeft());
++    QRect q = m_rolloverQuoteDialog->geometry();
++
++    // I don't understand why--perhaps due to the windowFlags--but q is already in global coordinates
++    q.moveBottom(gt.y() - 20);   
++    m_rolloverQuoteDialog->setGeometry(q);
++}
++
++void MainWindow::orderFabHoverLeave() {
++    //DebugDialog::debug("leave fab button");
++    if (m_rolloverQuoteDialog) {
++        m_rolloverQuoteDialog->hide();
++    }
++}
++
+diff -urN fritzing-0.8.3b.source.orig/src/mainwindow/mainwindow.h fritzing-0.8.3b.source/src/mainwindow/mainwindow.h
+--- fritzing-0.8.3b.source.orig/src/mainwindow/mainwindow.h	2013-07-27 14:03:38.000000000 -0700
++++ fritzing-0.8.3b.source/src/mainwindow/mainwindow.h	2013-08-10 22:49:23.904174341 -0700
+@@ -146,7 +146,6 @@
  	QSizeGrip *sizeGrip();
  	QStatusBar *realStatusBar();
  	void showAllFirstTimeHelp(bool show);
@@ -156,7 +3051,7 @@ diff -urN fritzing-0.7.12b.source.orig/src/mainwindow/mainwindow.h fritzing-0.7.
  
  	void getPartsEditorNewAnd(ItemBase * fromItem);
  	void addDefaultParts();
-@@ -776,7 +775,6 @@
+@@ -829,7 +828,6 @@
      QAction *m_partsRefAct;
      QAction *m_showInViewHelpAct;;
      QAction *m_visitFritzingDotOrgAct;
@@ -164,10 +3059,940 @@ diff -urN fritzing-0.7.12b.source.orig/src/mainwindow/mainwindow.h fritzing-0.7.
      QAction *m_aboutQtAct;
      QAction *m_reportBugAct;
  	QAction *m_enableDebugAct;
-diff -urN fritzing-0.7.12b.source.orig/src/mainwindow/mainwindow_menu.cpp fritzing-0.7.12b.source/src/mainwindow/mainwindow_menu.cpp
---- fritzing-0.7.12b.source.orig/src/mainwindow/mainwindow_menu.cpp	2013-02-25 05:02:59.000000000 -0800
-+++ fritzing-0.7.12b.source/src/mainwindow/mainwindow_menu.cpp	2013-02-25 18:29:22.843459092 -0800
-@@ -1098,10 +1098,6 @@
+diff -urN fritzing-0.8.3b.source.orig/src/mainwindow/mainwindow.h.orig fritzing-0.8.3b.source/src/mainwindow/mainwindow.h.orig
+--- fritzing-0.8.3b.source.orig/src/mainwindow/mainwindow.h.orig	1969-12-31 16:00:00.000000000 -0800
++++ fritzing-0.8.3b.source/src/mainwindow/mainwindow.h.orig	2013-07-27 14:03:38.000000000 -0700
+@@ -0,0 +1,926 @@
++/*******************************************************************
++
++Part of the Fritzing project - http://fritzing.org
++Copyright (c) 2007-2013 Fachhochschule Potsdam - http://fh-potsdam.de
++
++Fritzing is free software: you can redistribute it and/or modify
++it under the terms of the GNU General Public License as published by
++the Free Software Foundation, either version 3 of the License, or
++(at your option) any later version.
++
++Fritzing is distributed in the hope that it will be useful,
++but WITHOUT ANY WARRANTY; without even the implied warranty of
++MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++GNU General Public License for more details.
++
++You should have received a copy of the GNU General Public License
++along with Fritzing.  If not, see <http://www.gnu.org/licenses/>.
++
++********************************************************************
++
++$Revision: 6999 $:
++$Author: irascibl at gmail.com $:
++$Date: 2013-04-28 14:14:07 +0200 (So, 28. Apr 2013) $
++
++********************************************************************/
++
++#ifndef MAINWINDOW_H
++#define MAINWINDOW_H
++
++#include <QUndoView>
++#include <QUndoGroup>
++#include <QRadioButton>
++#include <QLineEdit>
++#include <QToolButton>
++#include <QPushButton>
++#include <QStackedWidget>
++#include <QSizeGrip>
++#include <QProcess>
++#include <QDockWidget>
++#include <QXmlStreamWriter>
++#include <QRegExp>
++
++#include "fritzingwindow.h"
++#include "sketchareawidget.h"
++#include "../viewlayer.h"
++#include "../program/programwindow.h"
++#include "../svg/svg2gerber.h"
++#include "../dock/viewswitcher.h"
++#include "../routingstatus.h"
++
++QT_BEGIN_NAMESPACE
++class QAction;
++class QListWidget;
++class QMenu;
++QT_END_NAMESPACE
++
++class Helper;
++class FSizeGrip;
++
++typedef class FDockWidget * (*DockFactory)(const QString & title, QWidget * parent);
++
++bool sortPartList(class ItemBase * b1, class ItemBase * b2);
++
++static const QString ORDERFABENABLED = "OrderFabEnabled";
++
++class SwapTimer : public QTimer
++{
++Q_OBJECT
++
++public:
++	SwapTimer();
++
++	void setAll(const QString & family, const QString & prop, QMap<QString, QString> &  propsMap, ItemBase *);
++	const QString & family();
++	const QString & prop();
++	QMap<QString, QString> propsMap();
++	ItemBase * itemBase();
++
++protected:
++	QString m_family;
++	QString m_prop;
++	QMap<QString, QString> m_propsMap;
++	QPointer <ItemBase> m_itemBase;
++};
++
++struct GridSizeThing
++{
++	QLineEdit * lineEdit;
++	QDoubleValidator * validator;
++	QRadioButton * mmButton;
++	QRadioButton * inButton;
++	double defaultGridSize;
++    QString gridSizeText;
++	QString viewName;
++	QString shortName;
++    
++    GridSizeThing(const QString & viewName, const QString & shortName, double defaultSize, const QString & gridSizeText);
++};
++
++class GridSizeDialog : public QDialog {
++    Q_OBJECT
++
++public:
++    GridSizeDialog(GridSizeThing *);
++    GridSizeThing * gridSizeThing();
++
++protected:
++    GridSizeThing * m_gridSizeThing;
++};
++
++
++struct TraceMenuThing {
++    int boardCount;
++    int boardSelectedCount;
++	bool jiEnabled;
++	bool exEnabled;
++	bool viaEnabled;
++	bool exChecked;
++	bool gfrEnabled;
++    bool gfsEnabled;
++
++    TraceMenuThing() {
++        boardCount = 0;
++        boardSelectedCount = 0;
++        gfsEnabled = false;
++        jiEnabled = false;
++	    exEnabled = false;
++	    exChecked = true;
++	    viaEnabled = false;
++	    gfrEnabled = false;
++    }
++};
++
++class MainWindow : public FritzingWindow
++{
++    Q_OBJECT
++public:
++    MainWindow(class ReferenceModel *referenceModel, QWidget * parent);
++    MainWindow(QFile & fileToLoad);
++	~MainWindow();
++
++    void mainLoad(const QString & fileName, const QString & displayName);
++	bool loadWhich(const QString & fileName, bool setAsLastOpened, bool addToRecent, const QString & displayName);
++	void notClosableForAWhile();
++	QAction *raiseWindowAction();
++	QSizeGrip *sizeGrip();
++	QStatusBar *realStatusBar();
++	void showAllFirstTimeHelp(bool show);
++	void enableCheckUpdates(bool enabled);
++
++	void getPartsEditorNewAnd(ItemBase * fromItem);
++	void addDefaultParts();
++    void init(ReferenceModel *referenceModel, bool lockFiles);
++	void showFileProgressDialog(const QString & path);
++	void setFileProgressPath(const QString & path);
++	void clearFileProgressDialog();
++	class FileProgressDialog * fileProgressDialog();
++
++	const QString &selectedModuleID();
++
++	void saveDocks();
++	void restoreDocks();
++
++	void redrawSketch();
++
++	// if we consider a part as the smallest ("atomic") entity inside
++	// fritzing, then this functions may help with the bundle tasks
++	// on the complex entities: sketches, bins, modules (?)
++	void saveBundledNonAtomicEntity(QString &filename, const QString &extension, Bundler *bundler, const QList<ModelPart*> &partsToSave, bool askForFilename, const QString & destFolderPath, bool saveModel, bool deleteLeftovers);
++	bool loadBundledNonAtomicEntity(const QString &filename, Bundler *bundler, bool addToBin, bool dontAsk);
++	void saveAsShareable(const QString & path, bool saveModel);
++
++	
++	void setCurrentFile(const QString &fileName, bool addToRecent, bool setAsLastOpened);
++	void setReportMissingModules(bool);
++	QList<class SketchWidget *> sketchWidgets();
++	void setCloseSilently(bool);
++	class PCBSketchWidget * pcbView();
++	void noBackup();
++	void swapSelectedAux(ItemBase * itemBase, const QString & moduleID, bool useViewLayerPlacement, ViewLayer::ViewLayerPlacement, QMap<QString, QString> & propsMap);
++    void swapLayers(ItemBase * itemBase, int layers, const QString & msg, int delay);
++	bool saveAsAux(const QString & fileName);
++	void swapObsolete(bool displayFeedback);
++	void selectAllObsolete(bool displayFeedback);
++	void hideTempPartsBin();
++	const QString & fritzingVersion();
++	void removeGroundFill(ViewLayer::ViewLayerID, QUndoCommand * parentCommand);
++	void groundFill(ViewLayer::ViewLayerID);
++	void copperFill(ViewLayer::ViewLayerID);
++    bool hasAnyAlien();
++    void exportSvg(double res, bool selectedItems, bool flatten, const QString & filename);
++    void setCurrentView(ViewLayer::ViewID);
++    bool usesPart(const QString & moduleID);
++    bool anyUsePart(const QString & moduleID);
++    bool updateParts(const QString & moduleID, QUndoCommand * parentCommand);
++	void updatePartsBin(const QString & moduleID);
++	bool hasCustomBoardShape();
++    void selectPartsWithModuleID(ModelPart *);
++    void addToSketch(QList<ModelPart *> &);
++	QStringList newDesignRulesCheck(bool showOkMessage);
++
++public:
++	static void initNames();
++	static MainWindow * newMainWindow(ReferenceModel *referenceModel, const QString & displayPath, bool showProgress, bool lockFiles);
++	static void setAutosavePeriod(int);
++	static void setAutosaveEnabled(bool);
++
++signals:
++	void alienPartsDismissed();
++	void viewSwitched(int);
++	void mainWindowMoved(QWidget *);
++	void changeActivationSignal(bool activate, QWidget * originator);
++	void externalProcessSignal(QString & name, QString & path, QStringList & args);
++
++public slots:
++	void ensureClosable();
++	ModelPart* loadBundledPart(const QString &fileName, bool addToBin);
++	void importFilesFromPrevInstall();
++	void acceptAlienFiles();
++	void statusMessage(QString message, int timeout);
++    void showPCBView();
++	void groundFill();
++	void removeGroundFill();
++	void copperFill();
++	void setOneGroundFillSeed();
++	void setGroundFillSeeds();	
++	void clearGroundFillSeeds();
++	void changeBoardLayers(int layers, bool doEmit);
++	void selectAllObsolete();
++	void swapObsolete();
++    void swapBoardImageSlot(SketchWidget * sketchWidget, ItemBase * itemBase, const QString & filename, const QString & moduleID, bool addName);
++	void updateTraceMenu();
++	virtual void updateFileMenu();
++    void showStatusMessage(const QString &);
++    void orderFabHoverEnter();
++    void orderFabHoverLeave();
++    void setGroundFillKeepout();
++
++protected slots:
++	void mainLoad();
++	void revert();
++	void openRecentOrExampleFile();
++    void print();
++    void doExport();
++	void exportEtchable();
++    void about();
++	void tipsAndTricks();
++    void copy();
++    void cut();
++    void paste();
++	void pasteInPlace();
++    void duplicate();
++    void doDelete();
++    void doDeleteMinus();
++    void selectAll();
++    void deselect();
++    void zoomIn();
++    void zoomOut();
++    void fitInWindow();
++    void actualSize();
++	void hundredPercentSize();
++    void alignToGrid();
++    void showGrid();
++    void setGridSize();
++    void setBackgroundColor();
++    void showBreadboardView();
++    void showSchematicView();
++    void showProgramView();
++	void showPartsBinIconView();
++	void showPartsBinListView();
++    void updateEditMenu();
++    virtual void updateLayerMenu(bool resetLayout = false);
++    void updatePartMenu();
++    virtual void updateWireMenu();
++    void updateTransformationActions();
++	void updateRecentFileActions();
++    virtual void tabWidget_currentChanged(int index);
++    void createNewSketch();
++    void minimize();
++    void toggleToolbar(bool toggle);
++    void togglePartLibrary(bool toggle);
++    void toggleInfo(bool toggle);
++    void toggleNavigator(bool toggle);
++    void toggleUndoHistory(bool toggle);
++	void toggleDebuggerOutput(bool toggle);
++	void openHelp();
++	void openDonate();
++	void openExamples();
++	void openPartsReference();
++	void visitFritzingDotOrg();
++	void partsEditorHelp();
++	virtual void updateWindowMenu();
++	void pageSetup();
++	void sendToBack();
++	void sendBackward();
++	void bringForward();
++	void bringToFront();
++    void alignLeft();
++    void alignRight();
++    void alignVerticalCenter();
++    void alignTop();
++    void alignHorizontalCenter();
++    void alignBottom();
++	void rotate90cw();
++	void rotate90ccw();
++	void rotate180();
++	void rotate45ccw();
++	void rotate45cw();
++	void rotateIncCCW();
++	void rotateIncCW();
++	void rotateIncCCWRubberBand();
++	void rotateIncCWRubberBand();
++	void flipHorizontal();
++	void flipVertical();
++	void showAllLayers();
++	void hideAllLayers();
++	void showInViewHelp();
++	void addBendpoint();
++	void convertToVia();
++	void convertToBendpoint();
++	void flattenCurve();
++	void disconnectAll();
++
++	void openInPartsEditorNew();
++	void openNewPartsEditor(class PaletteItem *);
++
++	void updateZoomSlider(double zoom);
++	void updateZoomOptionsNoMatterWhat(double zoom);
++	void updateViewZoom(double newZoom);
++
++	void setInfoViewOnHover(bool infoViewOnHover);
++	void updateItemMenu();
++
++	void newAutoroute();
++	void orderFab();
++	void activeLayerTop();
++	void activeLayerBottom();
++	void activeLayerBoth();
++	void toggleActiveLayer();
++	void createTrace();
++	void excludeFromAutoroute();
++	void selectAllTraces();
++	void showUnrouted();
++    void selectAllCopperFill();
++	void updateRoutingStatus();
++	void selectAllExcludedTraces();
++	void selectAllIncludedTraces();
++	void selectAllJumperItems();
++	void selectAllVias();
++
++	void shareOnline();
++	void saveBundledPart(const QString &moduleId=___emptyString___);
++	QStringList saveBundledAux(ModelPart *mp, const QDir &destFolder);
++
++	void binSaved(bool hasAlienParts);
++	void routingStatusSlot(class SketchWidget *, const RoutingStatus &);
++
++	void applyReadOnlyChange(bool isReadOnly);
++	void currentNavigatorChanged(class MiniViewContainer *);
++	void viewSwitchedTo(int viewIndex);
++
++	void raiseAndActivate();
++	void activateWindowAux();
++	void showPartLabels();
++	void addNote();
++	void reportBug();
++	void enableDebug();
++	void tidyWires();
++	void changeWireColor(bool checked);
++
++	void startSaveInstancesSlot(const QString & fileName, ModelPart *, QXmlStreamWriter &);
++	void loadedViewsSlot(class ModelBase *, QDomElement & views);
++	void loadedRootSlot(const QString & filename, ModelBase *, QDomElement & views);
++    void obsoleteSMDOrientationSlot();
++	void exportNormalizedSVG();
++	void exportNormalizedFlattenedSVG();
++
++	void launchExternalProcess();
++	bool externalProcess(QString & name, QString & path, QStringList & args);
++	void processError(QProcess::ProcessError processError);
++	void processFinished(int exitCode, QProcess::ExitStatus exitStatus);
++	void processReadyRead();
++	void processStateChanged(QProcess::ProcessState newState);
++    void throwFakeException();
++
++	void dropPaste(SketchWidget *);
++
++	void openProgramWindow();
++	void linkToProgramFile(const QString & filename, const QString & language, const QString & programmer, bool addLink, bool strong);
++	QStringList newDesignRulesCheck();
++	void subSwapSlot(SketchWidget *, ItemBase *, const QString & newModuleID, ViewLayer::ViewLayerPlacement, long & newID, QUndoCommand * parentCommand);
++	void updateLayerMenuSlot();
++	bool save();
++	bool saveAs();
++	virtual void backupSketch();
++	void undoStackCleanChanged(bool isClean);
++	void autosaveNeeded(int index = 0);
++	void firstTimeHelpHidden();
++	void changeTraceLayer();
++	void routingStatusLabelMousePress(QMouseEvent*);
++	void routingStatusLabelMouseRelease(QMouseEvent*);
++	void selectMoveLock();
++	void moveLock();
++	void setSticky();
++	void showNavigator();
++	void autorouterSettings();
++	void boardDeletedSlot();
++	void cursorLocationSlot(double, double);
++	void locationLabelClicked();
++	void swapSelectedMap(const QString & family, const QString & prop, QMap<QString, QString> & currPropsMap, ItemBase *);
++	void swapSelectedDelay(const QString & family, const QString & prop, QMap<QString, QString> & currPropsMap, ItemBase *);
++	void swapSelectedTimeout();
++	void filenameIfSlot(QString & filename);
++	void openURL();
++	void setActiveWire(class Wire *);
++	void setActiveConnectorItem(class ConnectorItem *);
++	void gridUnits(bool);
++	void restoreDefaultGrid();
++    void checkLoadedTraces();
++
++    void keepMargins();
++	void dockChangeActivation(bool activate, QWidget * originator);
++    void addToMyParts(ModelPart *);
++    void hidePartSilkscreen();
++    void fabQuote();
++    void findPartInSketch();
++    void fireQuote();
++    void setViewFromBelowToggle();
++    void setViewFromBelow();
++    void setViewFromAbove();
++
++protected:
++	void initSketchWidget(SketchWidget *);
++    virtual void initProgrammingWidget();
++
++    virtual void createActions();
++    virtual void createFileMenuActions();
++    void createExportActions();
++    void createRaiseWindowActions();
++    void createOrderFabAct();
++    void createOpenExampleMenu();
++	void createActiveLayerActions();
++    void populateMenuFromXMLFile(QMenu *parentMenu, QStringList &actionsTracker, const QString &folderPath, const QString &indexFileName);
++    QHash<QString, struct SketchDescriptor *> indexAvailableElements(QDomElement &domElem, const QString &srcPrefix, QStringList & actionsTracker);
++    void populateMenuWithIndex(const QHash<QString, struct SketchDescriptor *> &, QMenu * parentMenu, QDomElement &domElem);
++    void populateMenuFromFolderContent(QMenu *parentMenu, const QString &path);
++    void createOpenRecentMenu();
++    void createEditMenuActions();
++    void createPartMenuActions();
++    virtual void createViewMenuActions();
++    void createWindowMenuActions();
++    void createHelpMenuActions();
++    virtual void createMenus();
++    void createStatusBar();
++	virtual void connectPairs();
++	void connectPair(SketchWidget * signaller, SketchWidget * slotter);
++	void closeEvent(QCloseEvent * event);
++	void saveAsAuxAux(const QString & fileName);
++	void printAux(QPrinter &printer, bool removeBackground, bool paginate);
++	void exportAux(QString fileName, QImage::Format format, int quality, bool removeBackground);
++	void notYetImplemented(QString action);
++	bool eventFilter(QObject *obj, QEvent *event);
++	void setActionsIcons(int index, QList<QAction *> &);
++	void exportToEagle();
++	void exportToGerber();
++    void exportBOM();
++    void exportNetlist();
++    void exportSpiceNetlist();
++    void exportSvg(double res, bool selectedItems, bool flatten);
++	void exportSvgWatermark(QString & svg, double res);
++	void exportEtchable(bool wantPDF, bool wantSVG);
++
++	virtual QList<QWidget*> getButtonsForView(ViewLayer::ViewID viewId);
++	const QString untitledFileName();
++	int &untitledFileCount();
++	const QString fileExtension();
++	QString getExtensionString();
++	QStringList getExtensions();
++	const QString defaultSaveFolder();
++	bool undoStackIsEmpty();
++
++	void createTraceMenuActions();
++	void hideShowTraceMenu();
++    void hideShowProgramMenu();
++    void updatePCBTraceMenu(QGraphicsItem *, TraceMenuThing &);
++
++	QList<ModelPart*> moveToPartsFolder(QDir &unzipDir, MainWindow* mw, bool addToBin, bool addToAlien, const QString & prefixFolder, const QString &destFolder, bool importingSinglePart);
++	QString copyToSvgFolder(const QFileInfo& file, bool addToAlien, const QString & prefixFolder, const QString &destFolder);
++	ModelPart* copyToPartsFolder(const QFileInfo& file, bool addToAlien, const QString & prefixFolder, const QString &destFolder);
++
++	void closeIfEmptySketch(MainWindow* mw);
++	bool whatToDoWithAlienFiles();
++	void backupExistingFileIfExists(const QString &destFilePath);
++	void recoverBackupedFiles();
++	void resetTempFolder();
++
++	virtual QMenu *breadboardItemMenu();
++	virtual QMenu *schematicItemMenu();
++	virtual QMenu *pcbItemMenu();
++	virtual QMenu *pcbWireMenu();
++	virtual QMenu *schematicWireMenu();
++	virtual QMenu *breadboardWireMenu();
++
++	QMenu *viewItemMenuAux(QMenu* menu);
++
++	void createZoomOptions(SketchAreaWidget* parent);
++	class SketchToolButton *createRotateButton(SketchAreaWidget *parent);
++	SketchToolButton *createShareButton(SketchAreaWidget *parent);
++	SketchToolButton *createFlipButton(SketchAreaWidget *parent);
++	SketchToolButton *createAutorouteButton(SketchAreaWidget *parent);
++	SketchToolButton *createOrderFabButton(SketchAreaWidget *parent);
++	QWidget *createActiveLayerButton(SketchAreaWidget *parent);
++	QWidget *createViewFromButton(SketchAreaWidget *parent);
++	class ExpandingLabel * createRoutingStatusLabel(SketchAreaWidget *);
++	SketchToolButton *createExportEtchableButton(SketchAreaWidget *parent);
++	SketchToolButton *createNoteButton(SketchAreaWidget *parent);
++	QWidget *createToolbarSpacer(SketchAreaWidget *parent);
++	SketchAreaWidget *currentSketchArea();
++	const QString fritzingTitle();
++
++	virtual void updateRaiseWindowAction();
++
++	void moveEvent(QMoveEvent * event);
++	bool event(QEvent *);
++	void resizeEvent(QResizeEvent * event);
++	QString genIcon(SketchWidget *, LayerList &  partViewLayerIDs, LayerList & wireViewLayerIDs);
++
++	bool alreadyOpen(const QString & fileName);
++	void svgMissingLayer(const QString & layername, const QString & path);
++	long swapSelectedAuxAux(ItemBase * itemBase, const QString & moduleID, ViewLayer::ViewLayerPlacement viewLayerPlacement, QMap<QString, QString> & propsMap, QUndoCommand * parentCommand);
++	bool swapSpecial(const QString & prop, QMap<QString, QString> & currPropsMap);
++
++	void enableAddBendpointAct(QGraphicsItem *);
++	class FileProgressDialog * exportProgress();
++	QString constructFileName(const QString & differentiator, const QString & extension);
++	bool isGroundFill(ItemBase * itemBase);
++
++	QString getBoardSvg(ItemBase * board, int res, LayerList &);
++	QString mergeBoardSvg(QString & svg, ItemBase * board, int res, bool flip, LayerList &);
++
++	void updateActiveLayerButtons();
++	int activeLayerIndex();
++	bool hasLinkedProgramFiles(const QString & filename, QStringList & linkedProgramFiles);
++	void pasteAux(bool pasteInPlace);
++
++	void routingStatusLabelMouse(QMouseEvent*, bool show);
++	class Wire * retrieveWire();
++	class ConnectorItem * retrieveConnectorItem();
++	QString getBomProps(ItemBase *);
++	ModelPart * findReplacedby(ModelPart * originalModelPart);
++	void groundFillAux(bool fillGroundTraces, ViewLayer::ViewLayerID viewLayerID);
++    void groundFillAux2(bool fillGroundTraces);
++	void connectStartSave(bool connect);
++	void loadBundledSketch(const QString &fileName, bool addToRecent, bool setAsLastOpened);
++    void dropEvent(QDropEvent *event);
++    void dragEnterEvent(QDragEnterEvent *event);
++    void mainLoadAux(const QString & fileName);
++	QWidget * createGridSizeForm(GridSizeThing *);
++    void massageOutput(QString & svg, bool doMask, bool doSilk, bool doPaste, QString & maskTop, QString & maskBottom, const QString & fileName, ItemBase * board, int dpi, const LayerList &);
++    virtual void initLockedFiles(bool lockFiles);
++    virtual void initSketchWidgets();
++    virtual void initDock();
++    virtual void initMenus();
++    virtual void moreInitDock();
++    virtual void initHelper();
++    virtual void createFileMenu();
++    virtual void createEditMenu();
++    virtual void createPartMenu();
++    virtual void createViewMenu();
++    virtual void createWindowMenu();
++    virtual void createTraceMenus();
++    virtual void createHelpMenu();
++	virtual void populateExportMenu();
++
++    // dock management
++	void createDockWindows();
++	void dontKeepMargins();
++	class FDockWidget * makeDock(const QString & title, QWidget * widget, int dockMinHeight, int dockDefaultHeight, Qt::DockWidgetArea area = Qt::RightDockWidgetArea, DockFactory dockFactory = NULL);
++	class FDockWidget * dockIt(FDockWidget* dock, int dockMinHeight, int dockDefaultHeight, Qt::DockWidgetArea area = Qt::RightDockWidgetArea);
++	FDockWidget *newTopWidget();
++	FDockWidget *newBottomWidget();
++	void removeMargin(FDockWidget* dock);
++	void addTopMargin(FDockWidget* dock);
++	void addBottomMargin(FDockWidget* dock);
++	void dockMarginAux(FDockWidget* dock, const QString &name, const QString &style);
++    void initStyleSheet();
++    virtual QString getStyleSheetSuffix();
++	virtual QWidget * createTabWidget();
++	virtual void addTab(QWidget * widget, const QString & label);
++	virtual int currentTabIndex();
++	virtual void setCurrentTabIndex(int);
++	virtual QWidget * currentTabWidget();
++	virtual bool activeLayerWidgetAlwaysOn();
++    bool copySvg(const QString & path, QFileInfoList & svgEntryInfoList);
++
++protected:
++	static void removeActionsStartingAt(QMenu *menu, int start=0);
++	static void setAutosave(int, bool);
++
++protected:
++
++	QUndoGroup *m_undoGroup;
++	QUndoView *m_undoView;
++
++	QPointer<SketchAreaWidget> m_breadboardWidget;
++	QPointer<class BreadboardSketchWidget> m_breadboardGraphicsView;
++
++	QPointer<SketchAreaWidget> m_schematicWidget;
++	QPointer<class SchematicSketchWidget> m_schematicGraphicsView;
++
++	QPointer<SketchAreaWidget> m_pcbWidget;
++	QPointer<class PCBSketchWidget> m_pcbGraphicsView;
++
++    QPointer<class BinManager> m_binManager;
++    QPointer<class MiniViewContainer> m_miniViewContainerBreadboard;
++    QPointer<class MiniViewContainer> m_miniViewContainerSchematic;
++    QPointer<class MiniViewContainer> m_miniViewContainerPCB;
++	QList <class MiniViewContainer *> m_navigators;
++	QPointer<QWidget> m_tabWidget;
++    QPointer<ReferenceModel> m_referenceModel;
++    QPointer<class SketchModel> m_sketchModel;
++    QPointer<class HtmlInfoView> m_infoView;
++    QPointer<QToolBar> m_toolbar;
++
++    bool m_closing;
++	bool m_dontClose;
++    bool m_firstOpen;
++
++    QPointer<SketchAreaWidget> m_currentWidget;
++    QPointer<SketchWidget> m_currentGraphicsView;
++
++    //QToolBar *m_fileToolBar;
++    //QToolBar *m_editToolBar;
++
++    QAction *m_raiseWindowAct;
++
++    // Fritzing Menu
++    QMenu *m_fritzingMenu;
++    QAction *m_aboutAct;
++    QAction *m_tipsAndTricksAct;
++    QAction *m_preferencesAct;
++    QAction *m_quitAct;
++    QAction *m_exceptionAct;
++
++    // File Menu
++    enum { MaxRecentFiles = 10 };
++
++	QMenu *m_fileMenu;
++	QAction *m_newAct;
++	QAction *m_openAct;
++	QAction *m_revertAct;
++	QMenu *m_openRecentFileMenu;
++    QAction *m_openRecentFileActs[MaxRecentFiles];
++	QMenu *m_openExampleMenu;
++	QAction *m_saveAct;
++	QAction *m_saveAsAct;
++	QAction *m_pageSetupAct;
++	QAction *m_printAct;
++	QAction *m_shareOnlineAct;
++
++	QAction * m_launchExternalProcessAct;
++
++	QMenu *m_zOrderMenu;
++	QMenu *m_zOrderWireMenu;
++	QAction *m_bringToFrontAct;
++	QAction *m_bringForwardAct;
++	QAction *m_sendBackwardAct;
++	QAction *m_sendToBackAct;
++	class WireAction *m_bringToFrontWireAct;
++	class WireAction *m_bringForwardWireAct;
++	class WireAction *m_sendBackwardWireAct;
++	class WireAction *m_sendToBackWireAct;
++
++    QMenu *m_alignMenu;
++    QAction * m_alignVerticalCenterAct;
++    QAction * m_alignHorizontalCenterAct;
++    QAction * m_alignTopAct;
++    QAction * m_alignLeftAct;
++    QAction * m_alignBottomAct;
++    QAction * m_alignRightAct;
++
++	// Export Menu
++	QMenu *m_exportMenu;
++	QAction *m_exportJpgAct;
++	QAction *m_exportPsAct;
++	QAction *m_exportPngAct;
++	QAction *m_exportPdfAct;
++	QAction *m_exportEagleAct;
++	QAction *m_exportGerberAct;
++	QAction *m_exportEtchablePdfAct;
++	QAction *m_exportEtchableSvgAct;
++	QAction *m_exportBomAct;
++	QAction *m_exportNetlistAct;
++	QAction *m_exportSpiceNetlistAct;
++	QAction *m_exportSvgAct;
++
++    // Edit Menu
++    QMenu *m_editMenu;
++    QAction *m_undoAct;
++    QAction *m_redoAct;
++    QAction *m_cutAct;
++    QAction *m_copyAct;
++    QAction *m_pasteAct;
++    QAction *m_pasteInPlaceAct;
++    QAction *m_duplicateAct;
++    QAction *m_deleteAct;
++    QAction *m_deleteMinusAct;
++    class WireAction *m_deleteWireAct;
++    class WireAction *m_deleteWireMinusAct;
++    QAction *m_selectAllAct;
++    QAction *m_deselectAct;
++	QAction *m_addNoteAct;
++
++    // Part Menu
++    QMenu *m_partMenu;
++	QAction *m_infoViewOnHoverAction;
++	QAction *m_exportNormalizedSvgAction;
++	QAction *m_exportNormalizedFlattenedSvgAction;
++    QAction *m_openInPartsEditorNewAct;
++    QMenu *m_addToBinMenu;
++
++
++	QMenu *m_rotateMenu;
++	QAction *m_rotate90cwAct;
++	QAction *m_rotate180Act;
++	QAction *m_rotate90ccwAct;
++	QAction *m_rotate45ccwAct;
++	QAction *m_rotate45cwAct;
++
++	QAction *m_moveLockAct;
++	QAction *m_stickyAct;
++	QAction *m_selectMoveLockAct;
++	QAction *m_flipHorizontalAct;
++	QAction *m_flipVerticalAct;
++	QAction *m_showPartLabelAct;
++	QAction *m_saveBundledPart;
++	QAction *m_disconnectAllAct;
++	QAction *m_selectAllObsoleteAct;
++	QAction *m_swapObsoleteAct;
++    QAction *m_findPartInSketchAct;
++	QAction * m_openProgramWindowAct;
++
++	QAction *m_addBendpointAct;
++	QAction *m_convertToViaAct;
++	QAction *m_convertToBendpointAct;
++    QAction * m_convertToBendpointSeparator;
++	QAction *m_flattenCurveAct;
++    QAction *m_showAllLayersAct;
++	QAction *m_hideAllLayersAct;
++
++    QAction *m_hidePartSilkscreenAct;
++
++    // View Menu
++    QMenu *m_viewMenu;
++    QAction *m_zoomInAct;
++    QAction *m_zoomOutAct;
++    QAction *m_fitInWindowAct;
++    QAction *m_actualSizeAct;
++    QAction *m_100PercentSizeAct;
++    QAction *m_alignToGridAct;
++    QAction *m_showGridAct;
++    QAction *m_setGridSizeAct;
++    QAction *m_setBackgroundColorAct;
++    QAction *m_showBreadboardAct;
++    QAction *m_showSchematicAct;
++    QAction *m_showProgramAct;
++    QAction *m_showPCBAct;
++	QAction *m_showPartsBinIconViewAct;
++	QAction *m_showPartsBinListViewAct;
++    //QAction *m_toggleToolbarAct;
++    int m_numFixedActionsInViewMenu;
++
++    // Window Menu
++	QMenu *m_windowMenu;
++	QAction *m_minimizeAct;
++	QAction *m_togglePartLibraryAct;
++	QAction *m_toggleInfoAct;
++	QAction *m_toggleNavigatorAct;
++	QAction *m_toggleUndoHistoryAct;
++	QAction *m_toggleDebuggerOutputAct;
++	QAction *m_windowMenuSeparator;
++
++	// Trace Menu
++	QMenu *m_pcbTraceMenu;
++	QMenu *m_schematicTraceMenu;
++	QMenu *m_breadboardTraceMenu;
++	QAction *m_newAutorouteAct;
++	QAction *m_orderFabAct;
++	QAction *m_activeLayerTopAct;
++	QAction *m_activeLayerBottomAct;
++	QAction *m_activeLayerBothAct;
++	QAction *m_viewFromBelowToggleAct;
++	QAction *m_viewFromBelowAct;
++	QAction *m_viewFromAboveAct;
++	class WireAction *m_createTraceWireAct;
++	class WireAction *m_createWireWireAct;
++	QAction *m_createJumperAct;
++	QAction *m_changeTraceLayerAct;
++	class WireAction *m_changeTraceLayerWireAct;
++	QAction *m_excludeFromAutorouteAct;
++	class WireAction *m_excludeFromAutorouteWireAct;
++    QAction * m_showUnroutedAct;
++	QAction *m_selectAllTracesAct;
++	QAction *m_selectAllWiresAct;
++	QAction *m_selectAllCopperFillAct;
++	QAction *m_updateRoutingStatusAct;
++	QAction *m_selectAllExcludedTracesAct;
++	QAction *m_selectAllIncludedTracesAct;
++	QAction *m_selectAllJumperItemsAct;
++	QAction *m_selectAllViasAct;
++	QAction *m_groundFillAct;
++	QAction *m_removeGroundFillAct;
++	QAction *m_copperFillAct;
++	class ConnectorItemAction *m_setOneGroundFillSeedAct;
++	QAction *m_setGroundFillSeedsAct;
++	QAction *m_clearGroundFillSeedsAct;
++    QAction *m_setGroundFillKeepoutAct;
++	QAction *m_newDesignRulesCheckAct;
++	QAction *m_autorouterSettingsAct;
++	QAction *m_fabQuoteAct;
++	QAction *m_tidyWiresAct;
++	QAction *m_checkLoadedTracesAct;
++
++	// Help Menu
++    QMenu *m_helpMenu;
++    QAction *m_openHelpAct;
++    QAction *m_openDonateAct;
++    QAction *m_examplesAct;
++    QAction *m_partsRefAct;
++    QAction *m_showInViewHelpAct;;
++    QAction *m_visitFritzingDotOrgAct;
++    QAction *m_checkForUpdatesAct;
++    QAction *m_aboutQtAct;
++    QAction *m_reportBugAct;
++	QAction *m_enableDebugAct;
++    QAction *m_importFilesFromPrevInstallAct;
++	QAction *m_partsEditorHelpAct;
++
++	// Wire Color Menu
++	QMenu * m_breadboardWireColorMenu;
++	QMenu * m_schematicWireColorMenu;
++
++    // Dot icons
++    QIcon m_dotIcon;
++    QIcon m_emptyIcon;
++
++	QList<SketchToolButton*> m_rotateButtons;
++	QList<SketchToolButton*> m_flipButtons;
++	QStackedWidget * m_activeLayerButtonWidget;
++	QStackedWidget * m_viewFromButtonWidget;
++
++    bool m_comboboxChanged;
++    bool m_restarting;
++
++    QStringList m_alienFiles;
++    QString m_alienPartsMsg;
++    QStringList m_filesReplacedByAlienOnes;
++
++    QStringList m_openExampleActions;
++
++	QPointer<class TripleNavigator> m_tripleNavigator;
++	QDockWidget * m_navigatorDock;
++	QPointer<class FSizeGrip> m_sizeGrip;
++
++	friend class Helper;
++
++	QPointer<class ViewSwitcher> m_viewSwitcher;
++	QPointer<class ViewSwitcherDockWidget> m_viewSwitcherDock;
++
++	QPointer<Helper> m_helper;
++	QTimer m_setUpDockManagerTimer;
++	QPointer<class FileProgressDialog> m_fileProgressDialog;
++	QPointer<class ZoomSlider> m_zoomSlider;
++	QPointer<QLabel> m_locationLabel;
++	QString m_locationLabelUnits;
++
++	QByteArray m_externalProcessOutput;
++
++	QPointer<class LayerPalette> m_layerPalette;
++	QPointer<class ProgramWindow> m_programWindow;
++	QPointer<class ProgramWindow> m_programView;
++	QList<LinkedFile *>  m_linkedProgramFiles;
++	QString m_backupFileNameAndPath;
++	QTimer m_autosaveTimer;
++	bool m_autosaveNeeded;
++	bool m_backingUp;
++	QString m_bundledSketchName;
++	RoutingStatus m_routingStatus;
++	bool m_orderFabEnabled;		
++	bool m_closeSilently;
++	QString m_fzzFolder;
++	QHash<QString, struct LockedFile *> m_fzzFiles;
++	SwapTimer m_swapTimer;
++	QPointer<Wire> m_activeWire;
++	QPointer<ConnectorItem> m_activeConnectorItem;
++    bool m_addedToTemp;
++    QString m_settingsPrefix;
++
++    // dock management
++	QList<FDockWidget*> m_docks;
++	FDockWidget* m_topDock;
++	FDockWidget* m_bottomDock;
++	QString m_oldTopDockStyle;
++	QString m_oldBottomDockStyle;
++	bool m_dontKeepMargins;
++    QPointer<QDialog> m_rolloverQuoteDialog;
++    bool m_obsoleteSMDOrientation;
++
++public:
++	static int AutosaveTimeoutMinutes;
++	static bool AutosaveEnabled;
++	static QString BackupFolder;
++    static const int DockMinWidth;
++    static const int DockMinHeight;
++
++
++protected:
++	static const QString UntitledSketchName;
++	static int UntitledSketchIndex;
++	static int CascadeFactorX;
++	static int CascadeFactorY;
++    static QRegExp GuidMatcher;
++};
++
++
++#endif
+diff -urN fritzing-0.8.3b.source.orig/src/mainwindow/mainwindow_menu.cpp fritzing-0.8.3b.source/src/mainwindow/mainwindow_menu.cpp
+--- fritzing-0.8.3b.source.orig/src/mainwindow/mainwindow_menu.cpp	2013-07-27 14:03:38.000000000 -0700
++++ fritzing-0.8.3b.source/src/mainwindow/mainwindow_menu.cpp	2013-08-10 22:49:23.905174341 -0700
+@@ -1150,10 +1150,6 @@
  	m_visitFritzingDotOrgAct->setStatusTip(tr("www.fritzing.org"));
  	connect(m_visitFritzingDotOrgAct, SIGNAL(triggered(bool)), this, SLOT(visitFritzingDotOrg()));*/
  
@@ -178,7 +4003,7 @@ diff -urN fritzing-0.7.12b.source.orig/src/mainwindow/mainwindow_menu.cpp fritzi
  	m_aboutAct = new QAction(tr("&About"), this);
  	m_aboutAct->setStatusTip(tr("Show the application's about box"));
  	connect(m_aboutAct, SIGNAL(triggered()), this, SLOT(about()));
-@@ -1395,7 +1391,6 @@
+@@ -1459,7 +1455,6 @@
  	m_helpMenu->addSeparator();
      m_helpMenu->addAction(m_partsEditorHelpAct);
  	m_helpMenu->addSeparator();
@@ -186,3 +4011,4314 @@ diff -urN fritzing-0.7.12b.source.orig/src/mainwindow/mainwindow_menu.cpp fritzi
  	m_helpMenu->addAction(m_importFilesFromPrevInstallAct);
  	m_helpMenu->addSeparator();
  	m_helpMenu->addAction(m_reportBugAct);
+diff -urN fritzing-0.8.3b.source.orig/src/mainwindow/mainwindow_menu.cpp.orig fritzing-0.8.3b.source/src/mainwindow/mainwindow_menu.cpp.orig
+--- fritzing-0.8.3b.source.orig/src/mainwindow/mainwindow_menu.cpp.orig	1969-12-31 16:00:00.000000000 -0800
++++ fritzing-0.8.3b.source/src/mainwindow/mainwindow_menu.cpp.orig	2013-07-27 14:03:38.000000000 -0700
+@@ -0,0 +1,4307 @@
++/*******************************************************************
++
++Part of the Fritzing project - http://fritzing.org
++Copyright (c) 2007-2013 Fachhochschule Potsdam - http://fh-potsdam.de
++
++Fritzing is free software: you can redistribute it and/or modify
++it under the terms of the GNU General Public License as published by
++the Free Software Foundation, either version 3 of the License, or
++(at your option) any later version.
++
++Fritzing is distributed in the hope that it will be useful,
++but WITHOUT ANY WARRANTY; without even the implied warranty of
++MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++GNU General Public License for more details.
++
++You should have received a copy of the GNU General Public License
++along with Fritzing.  If not, see <http://www.gnu.org/licenses/>.
++
++********************************************************************
++
++$Revision: 6999 $:
++$Author: irascibl at gmail.com $:
++$Date: 2013-04-28 14:14:07 +0200 (So, 28. Apr 2013) $
++
++********************************************************************/
++
++#include <QtGui>
++#include <QSvgGenerator>
++#include <QColor>
++#include <QImageWriter>
++#include <QInputDialog>
++
++#include "mainwindow.h"
++#include "../debugdialog.h"
++#include "../waitpushundostack.h"
++#include "../partseditor/pemainwindow.h"
++#include "../help/aboutbox.h"
++#include "../autoroute/mazerouter/mazerouter.h"
++#include "../autoroute/autorouteprogressdialog.h"
++#include "../autoroute/drc.h"
++#include "../items/virtualwire.h"
++#include "../items/resizableboard.h"
++#include "../items/jumperitem.h"
++#include "../items/via.h"
++#include "../fsvgrenderer.h"
++#include "../items/note.h"
++#include "../eagle/fritzing2eagle.h"
++#include "../sketch/breadboardsketchwidget.h"
++#include "../sketch/schematicsketchwidget.h"
++#include "../sketch/pcbsketchwidget.h"
++#include "../partsbinpalette/binmanager/binmanager.h"
++#include "../utils/expandinglabel.h"
++#include "../infoview/htmlinfoview.h"
++#include "../utils/bendpointaction.h"
++#include "../sketch/fgraphicsscene.h"
++#include "../utils/fileprogressdialog.h"
++#include "../svg/svgfilesplitter.h"
++#include "../version/version.h"
++#include "../svg/groundplanegenerator.h"
++#include "../help/tipsandtricks.h"
++#include "../dialogs/setcolordialog.h"
++#include "../utils/folderutils.h"
++#include "../utils/graphicsutils.h"
++#include "../utils/textutils.h"
++#include "../connectors/ercdata.h"
++#include "../items/moduleidnames.h"
++#include "../dock/miniviewcontainer.h"
++#include "../utils/zoomslider.h"
++#include "../dock/layerpalette.h"
++#include "../program/programwindow.h"
++#include "../utils/autoclosemessagebox.h"
++#include "../processeventblocker.h"
++#include "../sketchtoolbutton.h"
++
++////////////////////////////////////////////////////////
++
++// help struct to create the example menu from a xml file
++struct SketchDescriptor {
++	SketchDescriptor(const QString &_id, const QString &_name, const QString &_src, QAction * _action) {
++		id = _id;
++		name = _name;
++		src = _src;
++		action = _action;
++	}
++
++	QString id;
++	QString name;
++	QString src;
++	QAction * action;
++};
++
++bool sortSketchDescriptors(SketchDescriptor * s1, SketchDescriptor * s2){
++    return s1->name.toLower() < s2->name.toLower();
++}
++
++////////////////////////////////////////////////////////
++
++GridSizeThing::GridSizeThing(const QString & vName, const QString & sName, double defaultSize, const QString & gsText) 
++{
++	defaultGridSize = defaultSize;
++	viewName = vName;
++	shortName = sName;
++    gridSizeText = gsText;
++}
++
++GridSizeDialog::GridSizeDialog(GridSizeThing * gridSizeThing) : QDialog() {
++    m_gridSizeThing = gridSizeThing;
++}
++
++GridSizeThing * GridSizeDialog::gridSizeThing() {
++    return m_gridSizeThing;
++}
++
++
++/////////////////////////////////////////////////////////
++
++void MainWindow::closeIfEmptySketch(MainWindow* mw) {
++	int cascFactorX; int cascFactorY;
++	// close empty sketch window if user opens from a file
++	if (FolderUtils::isEmptyFileName(mw->m_fwFilename, untitledFileName()) && mw->undoStackIsEmpty()) {
++		QTimer::singleShot(0, mw, SLOT(close()) );
++		cascFactorX = 0;
++		cascFactorY = 0;
++	} else {
++		cascFactorX = CascadeFactorX;
++		cascFactorY = CascadeFactorY;
++	}
++	mw->move(x()+cascFactorX,y()+cascFactorY);
++	mw->show();
++}
++
++void MainWindow::mainLoad() {
++	QString path;
++	// if it's the first time load is called use Documents folder
++	if(m_firstOpen){
++		path = defaultSaveFolder();
++		m_firstOpen = false;
++	}
++	else {
++		path = "";
++	}
++
++	QString fileName = FolderUtils::getOpenFileName(
++			this,
++			tr("Select a Fritzing File to Open"),
++			path,
++			tr("Fritzing Files (*%1 *%2 *%3 *%4 *%5);;Fritzing (*%1);;Fritzing Shareable (*%2);;Fritzing Part (*%3);;Fritzing Bin (*%4);;Fritzing Shareable Bin (*%5)")
++                .arg(FritzingSketchExtension)
++                .arg(FritzingBundleExtension)
++                .arg(FritzingBundledPartExtension)
++                .arg(FritzingBinExtension)
++                .arg(FritzingBundledBinExtension)
++		);
++
++    if (fileName.isEmpty()) return;
++
++    if (fileName.endsWith(FritzingBundledPartExtension)) {
++        m_binManager->importPartToMineBin(fileName);
++        return;
++    }
++
++    if (fileName.endsWith(FritzingBinExtension) || fileName.endsWith(FritzingBundledBinExtension)) {
++        m_binManager->openBinIn(fileName, false);
++        return;
++    }
++
++    mainLoadAux(fileName);
++}
++
++void MainWindow::mainLoadAux(const QString & fileName)
++{
++	if (fileName.isNull()) return;
++
++    if (!fileName.endsWith(FritzingSketchExtension) && !fileName.endsWith(FritzingBundleExtension)) {
++        loadWhich(fileName, false, false, "");  
++        return;
++    }
++
++	if (alreadyOpen(fileName)) return;
++
++	QFile file(fileName);
++	if (!file.exists()) {
++       QMessageBox::warning(this, tr("Fritzing"),
++                             tr("Cannot find file %1.")
++                             .arg(fileName));
++
++
++		return;
++	}
++
++
++
++    if (!file.open(QFile::ReadOnly | QFile::Text)) {
++        QMessageBox::warning(this, tr("Fritzing"),
++                             tr("Cannot read file  1 %1:\n%2.")
++                             .arg(fileName)
++                             .arg(file.errorString()));
++        return;
++    }
++
++    file.close();
++
++    MainWindow* mw = newMainWindow(m_referenceModel, fileName, true, true);
++	mw->loadWhich(fileName, true, true, "");
++    mw->clearFileProgressDialog();
++	closeIfEmptySketch(mw);
++}
++
++void MainWindow::revert() {
++	QMessageBox::StandardButton answer = QMessageBox::question(
++            this,
++            tr("Revert?"),
++            tr("This operation can not be undone--you will lose all of your changes."
++                "\n\nGo ahead and revert?"),
++            QMessageBox::Yes | QMessageBox::No,
++            QMessageBox::Yes
++    );
++    // TODO: make button texts translatable
++    if (answer != QMessageBox::Yes) {
++        return;
++    }	
++
++    MainWindow* mw = newMainWindow( m_referenceModel, fileName(), true, true);
++    mw->setGeometry(this->geometry());
++
++    QFileInfo info(fileName());
++    if (info.exists() || !FolderUtils::isEmptyFileName(this->m_fwFilename, untitledFileName())) {
++	    mw->loadWhich(fileName(), true, true, "");
++    }
++    else {
++	    mw->addDefaultParts();
++        mw->show();
++	    mw->hideTempPartsBin();
++    }
++
++    mw->clearFileProgressDialog();   
++
++    // TODO: restore zoom, scroll, etc. for each view
++    mw->setCurrentTabIndex(currentTabIndex());
++
++    this->setCloseSilently(true);
++    this->close();
++}
++
++bool MainWindow::loadWhich(const QString & fileName, bool setAsLastOpened, bool addToRecent, const QString & displayName)
++{
++	if (!QFileInfo(fileName).exists()) {
++		QMessageBox::warning(NULL, tr("Fritzing"), tr("File '%1' not found").arg(fileName));
++		return false;
++	}
++
++	bool result = false;
++    if (fileName.endsWith(FritzingSketchExtension)) {
++		QFileInfo info(fileName);
++		QMessageBox messageBox(NULL);
++		messageBox.setWindowTitle(tr("the .fz file format is obsolete"));
++		messageBox.setText(tr("The .fz file format has been deprecated.\n\nWould you like to convert '%1' to the .fzz format now or open it read-only?\n").arg(info.fileName()));
++		messageBox.setInformativeText(tr("The conversion process will not modify '%1'.").arg(info.fileName()));
++		messageBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel);
++		messageBox.setDefaultButton(QMessageBox::Yes);
++		messageBox.setIcon(QMessageBox::Question);
++		messageBox.setWindowModality(Qt::WindowModal);
++		messageBox.setButtonText(QMessageBox::Yes, tr("Convert"));
++		messageBox.setButtonText(QMessageBox::No, tr("Read-only"));
++		messageBox.setButtonText(QMessageBox::Cancel, tr("Cancel"));
++		QMessageBox::StandardButton answer = (QMessageBox::StandardButton) messageBox.exec();
++
++		if (answer == QMessageBox::Cancel) return false;
++
++		QString bundledFileName;
++		if (answer == QMessageBox::Yes) {
++			QString fileExt;
++			bundledFileName = FolderUtils::getSaveFileName(this, tr("Please specify an .fzz file name to save '%1' to").arg(info.fileName()), fileName + "z", tr("Fritzing (*%1)").arg(FritzingBundleExtension), &fileExt);
++			if (bundledFileName.isEmpty()) return false;	
++		}
++
++    	mainLoad(fileName, displayName);
++		result = true;
++
++		QFile file(fileName);
++		QDir dest(m_fzzFolder);
++		file.copy(dest.absoluteFilePath(info.fileName()));			// copy the .fz file directly
++
++		if (answer == QMessageBox::Yes) {
++			saveAsShareable(bundledFileName, false);					// false to prevent saving a bundle inside the bundle
++			setCurrentFile(bundledFileName, addToRecent, setAsLastOpened);
++		}
++		else {
++			this->setReadOnly(true);
++			setCurrentFile(fileName, false, false);
++		}
++    } 
++	else if(fileName.endsWith(FritzingBundleExtension)) {
++    	loadBundledSketch(fileName, addToRecent, setAsLastOpened);
++		result = true;
++    } 
++	else if (
++    		fileName.endsWith(FritzingBinExtension)
++    		|| fileName.endsWith(FritzingBundledBinExtension)
++    	) {
++		m_binManager->load(fileName);
++		result = true;
++	} 
++	else if (fileName.endsWith(FritzingPartExtension)) {
++		notYetImplemented(tr("directly loading parts"));
++	}  
++	else if (fileName.endsWith(FritzingBundledPartExtension)) {
++		loadBundledPart(fileName, true);
++		result = true;
++	}
++
++	if (result) {
++		this->show();
++	}
++
++	return result;
++}
++
++void MainWindow::mainLoad(const QString & fileName, const QString & displayName) {
++
++	if (m_fileProgressDialog) {
++		m_fileProgressDialog->setMaximum(200);
++		m_fileProgressDialog->setValue(102);
++	}
++	this->show();
++	showAllFirstTimeHelp(false);
++	ProcessEventBlocker::processEvents();
++
++
++	QString displayName2 = displayName;
++	if (displayName.isEmpty()) {
++		QFileInfo fileInfo(fileName);
++		displayName2 = fileInfo.fileName();
++	}
++
++	if (m_fileProgressDialog) {
++		m_fileProgressDialog->setMessage(tr("loading %1 (model)").arg(displayName2));
++		m_fileProgressDialog->setValue(110);
++	}
++	ProcessEventBlocker::processEvents();
++
++
++	QList<ModelPart *> modelParts;
++
++	connect(m_sketchModel, SIGNAL(loadedViews(ModelBase *, QDomElement &)),
++				this, SLOT(loadedViewsSlot(ModelBase *, QDomElement &)), Qt::DirectConnection);
++	connect(m_sketchModel, SIGNAL(loadedRoot(const QString &, ModelBase *, QDomElement &)),
++				this, SLOT(loadedRootSlot(const QString &, ModelBase *, QDomElement &)), Qt::DirectConnection);
++	connect(m_sketchModel, SIGNAL(obsoleteSMDOrientationSignal()),
++				this, SLOT(obsoleteSMDOrientationSlot()), Qt::DirectConnection);
++    m_obsoleteSMDOrientation = false;
++	m_sketchModel->loadFromFile(fileName, m_referenceModel, modelParts, true);
++
++	//DebugDialog::debug("core loaded");
++	disconnect(m_sketchModel, SIGNAL(loadedViews(ModelBase *, QDomElement &)),
++				this, SLOT(loadedViewsSlot(ModelBase *, QDomElement &)));
++	disconnect(m_sketchModel, SIGNAL(loadedRoot(const QString &, ModelBase *, QDomElement &)),
++				this, SLOT(loadedRootSlot(const QString &, ModelBase *, QDomElement &)));
++	disconnect(m_sketchModel, SIGNAL(obsoleteSMDOrientationSignal()),
++				this, SLOT(obsoleteSMDOrientationSlot()));
++
++	ProcessEventBlocker::processEvents();
++	if (m_fileProgressDialog) {
++		m_fileProgressDialog->setValue(155);
++		m_fileProgressDialog->setMessage(tr("loading %1 (breadboard)").arg(displayName2));
++	}
++
++	QList<long> newIDs;
++	m_breadboardGraphicsView->loadFromModelParts(modelParts, BaseCommand::SingleView, NULL, false, NULL, false, newIDs);
++
++	ProcessEventBlocker::processEvents();
++	if (m_fileProgressDialog) {
++		m_fileProgressDialog->setValue(170);
++		m_fileProgressDialog->setMessage(tr("loading %1 (pcb)").arg(displayName2));
++	}
++
++	newIDs.clear();
++	m_pcbGraphicsView->loadFromModelParts(modelParts, BaseCommand::SingleView, NULL, false, NULL, false, newIDs);
++                
++
++	ProcessEventBlocker::processEvents();
++	if (m_fileProgressDialog) {
++		m_fileProgressDialog->setValue(185);
++		m_fileProgressDialog->setMessage(tr("loading %1 (schematic)").arg(displayName2));
++	}
++
++	newIDs.clear();
++	m_schematicGraphicsView->loadFromModelParts(modelParts, BaseCommand::SingleView, NULL, false, NULL, false, newIDs);
++
++	ProcessEventBlocker::processEvents();
++	if (m_fileProgressDialog) {
++		m_fileProgressDialog->setValue(198);
++	}
++
++    if (m_obsoleteSMDOrientation) {
++        QSet<ItemBase *> toConvert;
++        foreach (QGraphicsItem * item, m_pcbGraphicsView->items()) {
++            ItemBase * itemBase = dynamic_cast<ItemBase *>(item);
++            if (itemBase == NULL) continue;
++
++            itemBase = itemBase->layerKinChief();
++            if (itemBase->modelPart()->flippedSMD() && itemBase->viewLayerPlacement() == ViewLayer::NewBottom) {
++                toConvert.insert(itemBase);
++            }
++        }
++
++        QList<ConnectorItem *> already;
++        foreach (ItemBase * itemBase, toConvert) {
++            PaletteItem * paletteItem = qobject_cast<PaletteItem *>(itemBase);
++            if (paletteItem == NULL) continue;          // shouldn't happen
++
++            paletteItem->rotateItem(180, true);
++        }
++    }
++
++    if (m_programView) {
++        QFileInfo fileInfo(m_fwFilename);
++        m_programView->linkFiles(m_linkedProgramFiles, fileInfo.absoluteDir().absolutePath());
++    }
++
++}
++
++void MainWindow::copy() {
++	if (m_currentGraphicsView == NULL) return;
++	m_currentGraphicsView->copy();
++}
++
++void MainWindow::cut() {
++	if (m_currentGraphicsView == NULL) return;
++	m_currentGraphicsView->cut();
++}
++
++void MainWindow::pasteInPlace() {
++	pasteAux(true);
++}
++
++void MainWindow::paste() {
++	pasteAux(false);
++}
++
++void MainWindow::pasteAux(bool pasteInPlace)
++{
++	if (m_currentGraphicsView == NULL) return;
++
++	QClipboard *clipboard = QApplication::clipboard();
++	if (clipboard == NULL) {
++		// shouldn't happen
++		return;
++	}
++
++	const QMimeData* mimeData = clipboard->mimeData(QClipboard::Clipboard);
++	if (mimeData == NULL) return;
++
++   	if (!mimeData->hasFormat("application/x-dnditemsdata")) return;
++
++    QByteArray itemData = mimeData->data("application/x-dnditemsdata");
++	QList<ModelPart *> modelParts;
++	QHash<QString, QRectF> boundingRects;
++	if (m_sketchModel->paste(m_referenceModel, itemData, modelParts, boundingRects, false)) {
++		QUndoCommand * parentCommand = new QUndoCommand("Paste");
++
++        QList<SketchWidget *> sketchWidgets;
++        sketchWidgets << m_breadboardGraphicsView << m_schematicGraphicsView << m_pcbGraphicsView;
++        sketchWidgets.removeOne(m_currentGraphicsView);
++        sketchWidgets.prepend(m_currentGraphicsView);
++
++		QList<long> newIDs;
++        foreach (SketchWidget * sketchWidget, sketchWidgets) {
++            newIDs.clear();
++            QRectF r;
++		    QRectF boundingRect = boundingRects.value(sketchWidget->viewName(), r);
++		    sketchWidget->loadFromModelParts(modelParts, BaseCommand::SingleView, parentCommand, true, pasteInPlace ? &r : &boundingRect, false, newIDs);
++        }
++
++		foreach (long id, newIDs) {
++			new IncLabelTextCommand(m_breadboardGraphicsView, id, parentCommand);
++		}
++
++        m_breadboardGraphicsView->setPasting(true);
++        m_pcbGraphicsView->setPasting(true);
++        m_schematicGraphicsView->setPasting(true);
++		m_undoStack->push(parentCommand);
++        m_breadboardGraphicsView->setPasting(false);
++        m_pcbGraphicsView->setPasting(false);
++        m_schematicGraphicsView->setPasting(false);
++	}
++
++    m_currentGraphicsView->updateInfoView();
++}
++
++void MainWindow::duplicate() {
++	if (m_currentGraphicsView == NULL) return;
++
++	m_currentGraphicsView->copy();
++	paste();
++
++	//m_currentGraphicsView->duplicate();
++}
++
++void MainWindow::doDelete() {
++	//DebugDialog::debug(QString("invoking do delete") );
++
++	if (m_currentGraphicsView != NULL) {
++		m_currentGraphicsView->deleteSelected(retrieveWire(), false);
++	}
++}
++
++void MainWindow::doDeleteMinus() {
++	if (m_currentGraphicsView != NULL) {
++		m_currentGraphicsView->deleteSelected(retrieveWire(), true);
++	}
++}
++
++void MainWindow::selectAll() {
++	if (m_currentGraphicsView != NULL) {
++		m_currentGraphicsView->selectDeselectAllCommand(true);
++	}
++}
++
++void MainWindow::deselect() {
++	if (m_currentGraphicsView != NULL) {
++		m_currentGraphicsView->selectDeselectAllCommand(false);
++	}
++}
++
++void MainWindow::about()
++{
++	AboutBox::showAbout();
++}
++
++void MainWindow::tipsAndTricks()
++{
++	TipsAndTricks::showTipsAndTricks();
++}
++
++void MainWindow::createActions()
++{
++    createRaiseWindowActions();
++
++    createFileMenuActions();
++    createEditMenuActions();
++    createPartMenuActions();
++    createViewMenuActions();
++    createWindowMenuActions();
++    createHelpMenuActions();
++	createTraceMenuActions();
++}
++
++void MainWindow::createRaiseWindowActions() {
++	m_raiseWindowAct = new QAction(m_fwFilename, this);
++	m_raiseWindowAct->setCheckable(true);
++	connect( m_raiseWindowAct, SIGNAL(triggered()), this, SLOT(raiseAndActivate()));
++	updateRaiseWindowAction();
++}
++
++void MainWindow::createFileMenuActions() {
++	m_newAct = new QAction(tr("New"), this);
++	m_newAct->setShortcut(tr("Ctrl+N"));
++	m_newAct->setStatusTip(tr("Create a new sketch"));
++	connect(m_newAct, SIGNAL(triggered()), this, SLOT(createNewSketch()));
++
++	m_openAct = new QAction(tr("&Open..."), this);
++	m_openAct->setShortcut(tr("Ctrl+O"));
++	m_openAct->setStatusTip(tr("Open a Fritzing sketch (.fzz, .fz), or load a Fritzing part (.fzpz), or a Fritzing parts bin (.fzb, .fzbz)"));
++	connect(m_openAct, SIGNAL(triggered()), this, SLOT(mainLoad()));
++
++	m_revertAct = new QAction(tr("Revert"), this);
++	m_revertAct->setStatusTip(tr("Reload the sketch"));
++	connect(m_revertAct, SIGNAL(triggered()), this, SLOT(revert()));
++
++	createOpenRecentMenu();
++	createOpenExampleMenu();
++	createCloseAction();
++	createExportActions();
++	createOrderFabAct();
++
++	QString name;
++	QString path;
++	QStringList args;
++	if (externalProcess(name, path, args)) {
++		m_launchExternalProcessAct = new QAction(name, this);
++		m_launchExternalProcessAct->setStatusTip(tr("Shell launch %1").arg(path));
++		connect(m_launchExternalProcessAct, SIGNAL(triggered()), this, SLOT(launchExternalProcess()));
++	}
++
++#ifndef QT_NO_DEBUG
++    m_exceptionAct = new QAction(tr("throw test exception"), this);
++    m_exceptionAct->setStatusTip(tr("throw a fake exception to see what happens"));
++    connect(m_exceptionAct, SIGNAL(triggered()), this, SLOT(throwFakeException()));
++#endif
++
++	m_quitAct = new QAction(tr("&Quit"), this);
++	m_quitAct->setShortcut(tr("Ctrl+Q"));
++	m_quitAct->setStatusTip(tr("Quit the application"));
++	connect(m_quitAct, SIGNAL(triggered()), qApp, SLOT(closeAllWindows2()));
++	m_quitAct->setMenuRole(QAction::QuitRole);
++
++}
++
++void MainWindow::createOpenExampleMenu() {
++	m_openExampleMenu = new QMenu(tr("&Open Example"), this);
++	QString folderPath = FolderUtils::getApplicationSubFolderPath("sketches")+"/";
++	populateMenuFromXMLFile(m_openExampleMenu, m_openExampleActions, folderPath, "index.xml");
++}
++
++void MainWindow::populateMenuFromXMLFile(QMenu *parentMenu, QStringList &actionsTracker, const QString &folderPath, const QString &indexFileName) 
++{
++	QDomDocument dom;
++	QFile file(folderPath+indexFileName);
++	dom.setContent(&file);
++
++	QDomElement domElem = dom.documentElement();
++	QDomElement indexDomElem = domElem.firstChildElement("sketches");
++	QDomElement taxonomyDomElem = domElem.firstChildElement("categories");
++
++	QHash<QString, struct SketchDescriptor *> index = indexAvailableElements(indexDomElem, folderPath, actionsTracker);
++	QList<SketchDescriptor *> sketchDescriptors(index.values());
++	qSort(sketchDescriptors.begin(), sketchDescriptors.end(), sortSketchDescriptors);
++
++	if (sketchDescriptors.size() > 0) {
++		// set up the "all" category
++		QDomElement all = dom.createElement("category");
++		all.setAttribute("name", tr("All"));
++		taxonomyDomElem.appendChild(all);
++		foreach (SketchDescriptor * sketchDescriptor, sketchDescriptors) {
++			QDomElement sketch = dom.createElement("sketch");
++			sketch.setAttribute("id", sketchDescriptor->id);
++			all.appendChild(sketch);
++		}
++	}
++	populateMenuWithIndex(index, parentMenu, taxonomyDomElem);
++	foreach (SketchDescriptor * sketchDescriptor, index.values()) {
++		delete sketchDescriptor;
++	}
++}
++
++QHash<QString, struct SketchDescriptor *> MainWindow::indexAvailableElements(QDomElement &domElem, const QString &srcPrefix, QStringList & actionsTracker) {
++	QHash<QString, struct SketchDescriptor *> retval;
++	QDomElement sketch = domElem.firstChildElement("sketch");
++	while(!sketch.isNull()) {
++		const QString id = sketch.attribute("id");
++		const QString name = sketch.attribute("name");
++		QString srcAux = sketch.attribute("src");
++		// if it's an absolute path, don't prefix it
++		const QString src = QFileInfo(srcAux).exists()? srcAux: srcPrefix+srcAux;
++		if(QFileInfo(src).exists()) {
++			actionsTracker << name;
++			QAction * action = new QAction(name, this);
++			action->setData(src);
++			connect(action,SIGNAL(triggered()),this,SLOT(openRecentOrExampleFile()));
++			retval[id] = new SketchDescriptor(id,name,src, action);
++		}
++		sketch = sketch.nextSiblingElement("sketch");
++	}
++	return retval;
++}
++
++void MainWindow::populateMenuWithIndex(const QHash<QString, struct SketchDescriptor *>  &index, QMenu * parentMenu, QDomElement &domElem) {
++	// note: the <sketch> element here is not the same as the <sketch> element in indexAvailableElements()
++	QDomElement e = domElem.firstChildElement();
++	while(!e.isNull()) {
++		if (e.nodeName() == "sketch") {
++			QString id = e.attribute("id");
++			if (!id.isEmpty()) {
++				if(index[id]) {
++					SketchDescriptor * sketchDescriptor = index[id];
++					parentMenu->addAction(sketchDescriptor->action);
++				} 
++				else 
++				{
++					qWarning() << tr("MainWindow::populateMenuWithIndex: couldn't load example with id='%1'").arg(id);
++				}
++			}
++		} 
++		else if (e.nodeName() == "category") {
++			QString name = e.attribute("name");
++			QMenu * currMenu = new QMenu(name, parentMenu);
++			parentMenu->addMenu(currMenu);
++			populateMenuWithIndex(index, currMenu, e);
++		}
++		else if (e.nodeName() == "separator") {
++			parentMenu->addSeparator();
++		}
++		else if (e.nodeName() == "url") {
++			QAction * action = new QAction(e.attribute("name"), this);
++			action->setData(e.attribute("href"));
++			connect(action, SIGNAL(triggered()), this, SLOT(openURL()));
++			parentMenu->addAction(action);
++		}
++		e = e.nextSiblingElement();
++	}
++}
++
++void MainWindow::populateMenuFromFolderContent(QMenu * parentMenu, const QString &path) {
++	QDir *currDir = new QDir(path);
++	QStringList content = currDir->entryList(QDir::AllEntries | QDir::NoDotAndDotDot);
++	if(content.size() > 0) {
++		for(int i=0; i < content.size(); i++) {
++			QString currFile = content.at(i);
++			QString currFilePath = currDir->absoluteFilePath(currFile);
++			if(QFileInfo(currFilePath).isDir()) {
++				QMenu * currMenu = new QMenu(currFile, parentMenu);
++				parentMenu->addMenu(currMenu);
++				populateMenuFromFolderContent(currMenu, currFilePath);
++			} else {
++				QString actionText = QFileInfo(currFilePath).completeBaseName();
++				m_openExampleActions << actionText;
++				QAction * currAction = new QAction(actionText, this);
++				currAction->setData(currFilePath);
++				connect(currAction,SIGNAL(triggered()),this,SLOT(openRecentOrExampleFile()));
++				parentMenu->addAction(currAction);
++			}
++		}
++	} else {
++		parentMenu->setEnabled(false);
++	}
++	delete currDir;
++}
++
++void MainWindow::createOpenRecentMenu() {
++	m_openRecentFileMenu = new QMenu(tr("&Open Recent Files"), this);
++
++	for (int i = 0; i < MaxRecentFiles; ++i) {
++		m_openRecentFileActs[i] = new QAction(this);
++		m_openRecentFileActs[i]->setVisible(false);
++		connect(m_openRecentFileActs[i], SIGNAL(triggered()),this, SLOT(openRecentOrExampleFile()));
++	}
++
++
++    for (int i = 0; i < MaxRecentFiles; ++i) {
++    	m_openRecentFileMenu->addAction(m_openRecentFileActs[i]);
++    }
++    updateRecentFileActions();
++}
++
++void MainWindow::updateFileMenu() {
++	updateRecentFileActions();
++	m_orderFabAct->setEnabled(true);
++
++    m_revertAct->setEnabled(m_undoStack->canUndo());
++}
++
++void MainWindow::updateRecentFileActions() {
++	QSettings settings;
++	QStringList files = settings.value("recentFileList").toStringList();
++	int ix = 0;
++	for (int i = 0; i < files.size(); ++i) {
++		QFileInfo finfo(files[i]);
++		if (!finfo.exists()) continue;
++
++		QString text = tr("&%1 %2").arg(ix + 1).arg(finfo.fileName());
++		m_openRecentFileActs[ix]->setText(text);
++		m_openRecentFileActs[ix]->setData(files[i]);
++		m_openRecentFileActs[ix]->setVisible(true);
++		if (++ix >= (int) MaxRecentFiles) {
++			break;
++		}
++	}
++
++	for (int j = ix; j < MaxRecentFiles; ++j) {
++		m_openRecentFileActs[j]->setVisible(false);
++	}
++
++	m_openRecentFileMenu->setEnabled(ix > 0);
++}
++
++void MainWindow::createEditMenuActions() {
++	m_undoAct = m_undoGroup->createUndoAction(this, tr("Undo"));
++	m_undoAct->setShortcuts(QKeySequence::Undo);
++	m_undoAct->setText(tr("Undo"));
++
++	m_redoAct = m_undoGroup->createRedoAction(this, tr("Redo"));
++	m_redoAct->setShortcuts(QKeySequence::Redo);
++	m_redoAct->setText(tr("Redo"));
++
++	m_cutAct = new QAction(tr("&Cut"), this);
++	m_cutAct->setShortcut(tr("Ctrl+X"));
++	m_cutAct->setStatusTip(tr("Cut selection"));
++	connect(m_cutAct, SIGNAL(triggered()), this, SLOT(cut()));
++
++	m_copyAct = new QAction(tr("&Copy"), this);
++	m_copyAct->setShortcut(tr("Ctrl+C"));
++	m_copyAct->setStatusTip(tr("Copy selection"));
++	connect(m_copyAct, SIGNAL(triggered()), this, SLOT(copy()));
++
++	m_pasteAct = new QAction(tr("&Paste"), this);
++	m_pasteAct->setShortcut(tr("Ctrl+V"));
++	m_pasteAct->setStatusTip(tr("Paste clipboard contents"));
++	connect(m_pasteAct, SIGNAL(triggered()), this, SLOT(paste()));
++
++	m_pasteInPlaceAct = new QAction(tr("Paste in Place"), this);
++	m_pasteInPlaceAct->setShortcut(tr("Ctrl+B"));
++	m_pasteInPlaceAct->setStatusTip(tr("Paste clipboard contents in place"));
++	connect(m_pasteInPlaceAct, SIGNAL(triggered()), this, SLOT(pasteInPlace()));
++
++	m_duplicateAct = new QAction(tr("&Duplicate"), this);
++	m_duplicateAct->setShortcut(tr("Ctrl+D"));
++	m_duplicateAct->setStatusTip(tr("Duplicate selection"));
++	connect(m_duplicateAct, SIGNAL(triggered()), this, SLOT(duplicate()));
++
++	m_deleteAct = new QAction(tr("&Delete"), this);
++	m_deleteAct->setStatusTip(tr("Delete selection"));
++	connect(m_deleteAct, SIGNAL(triggered()), this, SLOT(doDelete()));
++	#ifdef Q_WS_MAC
++		m_deleteAct->setShortcut(Qt::Key_Backspace);
++	#else
++		m_deleteAct->setShortcut(QKeySequence::Delete);
++	#endif
++
++    m_deleteMinusAct = new QAction(tr("Delete Minus"), this);
++	m_deleteMinusAct->setStatusTip(tr("Delete selection without attached wires"));
++	connect(m_deleteMinusAct, SIGNAL(triggered()), this, SLOT(doDeleteMinus()));
++
++	m_deleteWireAct = new WireAction(m_deleteAct);
++	m_deleteWireAct->setText(tr("&Delete Wire"));
++	connect(m_deleteWireAct, SIGNAL(triggered()), this, SLOT(doDelete()));
++
++	m_deleteWireMinusAct = new WireAction(m_deleteMinusAct);
++	m_deleteWireMinusAct->setText(tr("Delete Wire up to bendpoints"));
++	connect(m_deleteWireMinusAct, SIGNAL(triggered()), this, SLOT(doDeleteMinus()));
++
++	m_selectAllAct = new QAction(tr("&Select All"), this);
++	m_selectAllAct->setShortcut(tr("Ctrl+A"));
++	m_selectAllAct->setStatusTip(tr("Select all elements"));
++	connect(m_selectAllAct, SIGNAL(triggered()), this, SLOT(selectAll()));
++
++	m_deselectAct = new QAction(tr("&Deselect"), this);
++	m_deselectAct->setStatusTip(tr("Deselect"));
++	connect(m_deselectAct, SIGNAL(triggered()), this, SLOT(deselect()));
++
++	m_addNoteAct = new QAction(tr("Add Note"), this);
++	m_addNoteAct->setStatusTip(tr("Add a note"));
++	connect(m_addNoteAct, SIGNAL(triggered()), this, SLOT(addNote()));
++
++	m_preferencesAct = new QAction(tr("&Preferences..."), this);
++	m_preferencesAct->setStatusTip(tr("Show the application's about box"));
++	m_preferencesAct->setMenuRole(QAction::PreferencesRole);						// make sure this is added to the correct menu on mac
++	connect(m_preferencesAct, SIGNAL(triggered()), QApplication::instance(), SLOT(preferences()));
++}
++
++void MainWindow::createPartMenuActions() {
++	m_openInPartsEditorNewAct = new QAction(tr("Edit (new parts editor)"), this);
++	m_openInPartsEditorNewAct->setStatusTip(tr("Open the new parts editor on an existing part"));
++	connect(m_openInPartsEditorNewAct, SIGNAL(triggered()), this, SLOT(openInPartsEditorNew()));
++
++	m_addToBinMenu = new QMenu(tr("&Add to bin..."), this);
++	m_addToBinMenu->setStatusTip(tr("Add selected part to bin"));
++
++	m_disconnectAllAct = new QAction(tr("Disconnect All Wires"), this);
++	m_disconnectAllAct->setStatusTip(tr("Disconnect all wires connected to this connector"));
++	connect(m_disconnectAllAct, SIGNAL(triggered()), this, SLOT(disconnectAll()));
++
++#ifndef QT_NO_DEBUG
++	m_infoViewOnHoverAction = new QAction(tr("Update InfoView on hover"), this);
++	m_infoViewOnHoverAction->setCheckable(true);
++	bool infoViewOnHover = true;
++	m_infoViewOnHoverAction->setChecked(infoViewOnHover);
++	setInfoViewOnHover(infoViewOnHover);
++	connect(m_infoViewOnHoverAction, SIGNAL(toggled(bool)), this, SLOT(setInfoViewOnHover(bool)));
++
++	m_exportNormalizedSvgAction = new QAction(tr("Export Normalized SVG"), this);
++	m_exportNormalizedSvgAction->setStatusTip(tr("Export 1000 dpi SVG of this part in this view"));
++	connect(m_exportNormalizedSvgAction, SIGNAL(triggered()), this, SLOT(exportNormalizedSVG()));
++	
++	m_exportNormalizedFlattenedSvgAction = new QAction(tr("Export Normalized Flattened SVG"), this);
++	m_exportNormalizedFlattenedSvgAction->setStatusTip(tr("Export 1000 dpi Flattened SVG of this part in this view"));
++	connect(m_exportNormalizedFlattenedSvgAction, SIGNAL(triggered()), this, SLOT(exportNormalizedFlattenedSVG()));
++#endif
++
++
++	m_rotate45cwAct = new QAction(tr("Rotate 45\x00B0 Clockwise"), this);
++	m_rotate45cwAct->setStatusTip(tr("Rotate current selection 45 degrees clockwise"));
++	connect(m_rotate45cwAct, SIGNAL(triggered()), this, SLOT(rotate45cw()));
++
++	m_rotate90cwAct = new QAction(tr("Rotate 90\x00B0 Clockwise"), this);
++	m_rotate90cwAct->setStatusTip(tr("Rotate the selected parts by 90 degrees clockwise"));
++	connect(m_rotate90cwAct, SIGNAL(triggered()), this, SLOT(rotate90cw()));
++
++	m_rotate180Act = new QAction(tr("Rotate 180\x00B0"), this);
++	m_rotate180Act->setStatusTip(tr("Rotate the selected parts by 180 degrees"));
++	connect(m_rotate180Act, SIGNAL(triggered()), this, SLOT(rotate180()));
++
++	m_rotate90ccwAct = new QAction(tr("Rotate 90\x00B0 Counter Clockwise"), this);
++	m_rotate90ccwAct->setStatusTip(tr("Rotate current selection 90 degrees counter clockwise"));
++	connect(m_rotate90ccwAct, SIGNAL(triggered()), this, SLOT(rotate90ccw()));
++
++	m_rotate45ccwAct = new QAction(tr("Rotate 45\x00B0 Counter Clockwise"), this);
++	m_rotate45ccwAct->setStatusTip(tr("Rotate current selection 45 degrees counter clockwise"));
++	connect(m_rotate45ccwAct, SIGNAL(triggered()), this, SLOT(rotate45ccw()));
++
++	m_flipHorizontalAct = new QAction(tr("&Flip Horizontal"), this);
++	m_flipHorizontalAct->setStatusTip(tr("Flip current selection horizontally"));
++	connect(m_flipHorizontalAct, SIGNAL(triggered()), this, SLOT(flipHorizontal()));
++
++	m_flipVerticalAct = new QAction(tr("&Flip Vertical"), this);
++	m_flipVerticalAct->setStatusTip(tr("Flip current selection vertically"));
++	connect(m_flipVerticalAct, SIGNAL(triggered()), this, SLOT(flipVertical()));
++
++	m_bringToFrontAct = new QAction(tr("Bring to Front"), this);
++	m_bringToFrontAct->setShortcut(tr("Shift+Ctrl+]"));
++    m_bringToFrontAct->setStatusTip(tr("Bring selected object(s) to front of their layer"));
++    connect(m_bringToFrontAct, SIGNAL(triggered()), this, SLOT(bringToFront()));
++	m_bringToFrontWireAct = new WireAction(m_bringToFrontAct);
++    connect(m_bringToFrontWireAct, SIGNAL(triggered()), this, SLOT(bringToFront()));
++
++	m_bringForwardAct = new QAction(tr("Bring Forward"), this);
++	m_bringForwardAct->setShortcut(tr("Ctrl+]"));
++    m_bringForwardAct->setStatusTip(tr("Bring selected object(s) forward in their layer"));
++    connect(m_bringForwardAct, SIGNAL(triggered()), this, SLOT(bringForward()));
++	m_bringForwardWireAct = new WireAction(m_bringForwardAct);
++    connect(m_bringForwardWireAct, SIGNAL(triggered()), this, SLOT(bringForward()));
++
++	m_sendBackwardAct = new QAction(tr("Send Backward"), this);
++	m_sendBackwardAct->setShortcut(tr("Ctrl+["));
++    m_sendBackwardAct->setStatusTip(tr("Send selected object(s) back in their layer"));
++    connect(m_sendBackwardAct, SIGNAL(triggered()), this, SLOT(sendBackward()));
++	m_sendBackwardWireAct = new WireAction(m_sendBackwardAct);
++    connect(m_sendBackwardWireAct, SIGNAL(triggered()), this, SLOT(sendBackward()));
++
++	m_sendToBackAct = new QAction(tr("Send to Back"), this);
++	m_sendToBackAct->setShortcut(tr("Shift+Ctrl+["));
++    m_sendToBackAct->setStatusTip(tr("Send selected object(s) to the back of their layer"));
++    connect(m_sendToBackAct, SIGNAL(triggered()), this, SLOT(sendToBack()));
++	m_sendToBackWireAct = new WireAction(m_sendToBackAct);
++    connect(m_sendToBackWireAct, SIGNAL(triggered()), this, SLOT(sendToBack()));
++
++	m_alignLeftAct = new QAction(tr("Align Left"), this);
++    m_alignLeftAct->setStatusTip(tr("Align selected items at the left"));
++    connect(m_alignLeftAct, SIGNAL(triggered()), this, SLOT(alignLeft()));
++
++	m_alignHorizontalCenterAct = new QAction(tr("Align Horizontal Center"), this);
++    m_alignHorizontalCenterAct->setStatusTip(tr("Align selected items at the horizontal center"));
++    connect(m_alignHorizontalCenterAct, SIGNAL(triggered()), this, SLOT(alignHorizontalCenter()));
++
++    m_alignRightAct = new QAction(tr("Align Right"), this);
++    m_alignRightAct->setStatusTip(tr("Align selected items at the right"));
++    connect(m_alignRightAct, SIGNAL(triggered()), this, SLOT(alignRight()));
++
++    m_alignTopAct = new QAction(tr("Align Top"), this);
++    m_alignTopAct->setStatusTip(tr("Align selected items at the top"));
++    connect(m_alignTopAct, SIGNAL(triggered()), this, SLOT(alignTop()));
++
++	m_alignVerticalCenterAct = new QAction(tr("Align Vertical Center"), this);
++    m_alignVerticalCenterAct->setStatusTip(tr("Align selected items at the vertical center"));
++    connect(m_alignVerticalCenterAct, SIGNAL(triggered()), this, SLOT(alignVerticalCenter()));
++
++	m_alignBottomAct = new QAction(tr("Align Bottom"), this);
++    m_alignBottomAct->setStatusTip(tr("Align selected items at the bottom"));
++    connect(m_alignBottomAct, SIGNAL(triggered()), this, SLOT(alignBottom()));
++
++	m_moveLockAct = new QAction(tr("Lock Part"), this);
++    m_moveLockAct->setStatusTip(tr("Prevent a part from being moved"));
++	m_moveLockAct->setCheckable(true);
++    connect(m_moveLockAct, SIGNAL(triggered()), this, SLOT(moveLock()));
++
++	m_stickyAct = new QAction(tr("Sticky"), this);
++    m_stickyAct->setStatusTip(tr("If a \"sticky\" part is moved, parts on top of it are also moved"));
++	m_stickyAct->setCheckable(true);
++    connect(m_stickyAct, SIGNAL(triggered()), this, SLOT(setSticky()));
++
++	m_selectMoveLockAct = new QAction(tr("Select All Locked Parts"), this);
++    m_selectMoveLockAct->setStatusTip(tr("Select all parts that can't be moved"));
++    connect(m_selectMoveLockAct, SIGNAL(triggered()), this, SLOT(selectMoveLock()));
++
++	m_showPartLabelAct = new QAction(tr("&Show part label"), this);
++	m_showPartLabelAct->setStatusTip(tr("Show/hide the label for the selected parts"));
++	connect(m_showPartLabelAct, SIGNAL(triggered()), this, SLOT(showPartLabels()));
++
++	m_saveBundledPart = new QAction(tr("&Export..."), this);
++	m_saveBundledPart->setStatusTip(tr("Export selected part"));
++	connect(m_saveBundledPart, SIGNAL(triggered()), this, SLOT(saveBundledPart()));
++
++	m_addBendpointAct = new BendpointAction(tr("Add Bendpoint"), this);
++	m_addBendpointAct->setStatusTip(tr("Add a bendpoint to the selected wire"));
++	connect(m_addBendpointAct, SIGNAL(triggered()), this, SLOT(addBendpoint()));
++
++	m_convertToViaAct = new BendpointAction(tr("Convert Bendpoint to Via"), this);
++	m_convertToViaAct->setStatusTip(tr("Convert the bendpoint to a via"));
++	connect(m_convertToViaAct, SIGNAL(triggered()), this, SLOT(convertToVia()));
++
++	m_convertToBendpointAct = new QAction(tr("Convert Via to Bendpoint"), this);
++	m_convertToBendpointAct->setStatusTip(tr("Convert the via to a bendpoint"));
++	connect(m_convertToBendpointAct, SIGNAL(triggered()), this, SLOT(convertToBendpoint()));
++
++	m_flattenCurveAct = new BendpointAction(tr("Straighten Curve"), this);
++	m_flattenCurveAct->setStatusTip(tr("Straighten the curve of the selected wire"));
++	connect(m_flattenCurveAct, SIGNAL(triggered()), this, SLOT(flattenCurve()));
++
++    m_selectAllObsoleteAct = new QAction(tr("Select outdated parts"), this);
++    m_selectAllObsoleteAct->setStatusTip(tr("Select outdated parts"));
++	connect(m_selectAllObsoleteAct, SIGNAL(triggered()), this, SLOT(selectAllObsolete()));
++
++    m_swapObsoleteAct = new QAction(tr("Update selected parts"), this);
++    m_swapObsoleteAct->setStatusTip(tr("Update selected parts"));
++	connect(m_swapObsoleteAct, SIGNAL(triggered()), this, SLOT(swapObsolete()));
++
++    m_findPartInSketchAct = new QAction(tr("Find part in sketch..."), this);
++    m_findPartInSketchAct->setStatusTip(tr("Search for parts in a sketch by matching text"));
++	connect(m_findPartInSketchAct, SIGNAL(triggered()), this, SLOT(findPartInSketch()));
++
++    m_openProgramWindowAct = new QAction(tr("Open programming window"), this);
++    m_openProgramWindowAct->setStatusTip(tr("Open microcontroller programming window"));
++	connect(m_openProgramWindowAct, SIGNAL(triggered()), this, SLOT(openProgramWindow()));
++
++	m_hidePartSilkscreenAct = new QAction(tr("Hide part silkscreen"), this);
++	m_hidePartSilkscreenAct->setStatusTip(tr("Hide/show the silkscreen layer for only this part"));
++	connect(m_hidePartSilkscreenAct, SIGNAL(triggered()), this, SLOT(hidePartSilkscreen()));
++
++
++}
++
++void MainWindow::createViewMenuActions() {
++	m_zoomInAct = new QAction(tr("&Zoom In"), this);
++	m_zoomInAct->setShortcut(tr("Ctrl++"));
++	m_zoomInAct->setStatusTip(tr("Zoom in"));
++	connect(m_zoomInAct, SIGNAL(triggered()), this, SLOT(zoomIn()));
++
++	// instead of creating a filter to grab the shortcut, let's create a new action
++	// and append it to the window
++	QAction *zoomInAux = new QAction(this);
++	zoomInAux->setShortcut(tr("Ctrl+="));
++	connect(zoomInAux, SIGNAL(triggered()), this, SLOT(zoomIn()));
++	this->addAction(zoomInAux);
++
++	m_zoomOutAct = new QAction(tr("&Zoom Out"), this);
++	m_zoomOutAct->setShortcut(tr("Ctrl+-"));
++	m_zoomOutAct->setStatusTip(tr("Zoom out"));
++	connect(m_zoomOutAct, SIGNAL(triggered()), this, SLOT(zoomOut()));
++
++	m_fitInWindowAct = new QAction(tr("&Fit in Window"), this);
++	m_fitInWindowAct->setShortcut(tr("Ctrl+0"));
++	m_fitInWindowAct->setStatusTip(tr("Fit in window"));
++	connect(m_fitInWindowAct, SIGNAL(triggered()), this, SLOT(fitInWindow()));
++
++	m_actualSizeAct = new QAction(tr("&Actual Size"), this);
++	m_actualSizeAct->setStatusTip(tr("Actual (real world physical) size"));
++	connect(m_actualSizeAct, SIGNAL(triggered()), this, SLOT(actualSize()));
++
++	m_100PercentSizeAct = new QAction(tr("100% Size"), this);
++	m_100PercentSizeAct->setShortcut(tr("Shift+Ctrl+0"));
++	m_100PercentSizeAct->setStatusTip(tr("100% (pixel) size"));
++	connect(m_100PercentSizeAct, SIGNAL(triggered()), this, SLOT(hundredPercentSize()));
++
++	m_alignToGridAct = new QAction(tr("Align to Grid"), this);
++	m_alignToGridAct->setStatusTip(tr("Align items to grid when dragging"));
++	m_alignToGridAct->setCheckable(true);
++	connect(m_alignToGridAct, SIGNAL(triggered()), this, SLOT(alignToGrid()));
++
++	m_showGridAct = new QAction(tr("Show Grid"), this);
++	m_showGridAct->setStatusTip(tr("Show the grid"));
++	m_showGridAct->setCheckable(true);
++	connect(m_showGridAct, SIGNAL(triggered()), this, SLOT(showGrid()));
++
++	m_setGridSizeAct = new QAction(tr("Set Grid Size..."), this);
++	m_setGridSizeAct->setStatusTip(tr("Set the size of the grid in this view"));
++	connect(m_setGridSizeAct, SIGNAL(triggered()), this, SLOT(setGridSize()));
++
++	m_setBackgroundColorAct = new QAction(tr("Set Background Color..."), this);
++	m_setBackgroundColorAct->setStatusTip(tr("Set the background color of this view"));
++	connect(m_setBackgroundColorAct, SIGNAL(triggered()), this, SLOT(setBackgroundColor()));
++
++	m_showBreadboardAct = new QAction(tr("&Show Breadboard"), this);
++	m_showBreadboardAct->setShortcut(tr("Ctrl+1"));
++	m_showBreadboardAct->setStatusTip(tr("Show the breadboard view"));
++	connect(m_showBreadboardAct, SIGNAL(triggered()), this, SLOT(showBreadboardView()));
++
++	m_showSchematicAct = new QAction(tr("&Show Schematic"), this);
++	m_showSchematicAct->setShortcut(tr("Ctrl+2"));
++	m_showSchematicAct->setStatusTip(tr("Show the schematic view"));
++	connect(m_showSchematicAct, SIGNAL(triggered()), this, SLOT(showSchematicView()));
++
++	m_showPCBAct = new QAction(tr("&Show PCB"), this);
++	m_showPCBAct->setShortcut(tr("Ctrl+3"));
++	m_showPCBAct->setStatusTip(tr("Show the PCB view"));
++	connect(m_showPCBAct, SIGNAL(triggered()), this, SLOT(showPCBView()));
++
++    if (m_programView) {
++	    m_showProgramAct = new QAction(tr("Show Code"), this);
++	    m_showProgramAct->setShortcut(tr("Ctrl+4"));
++	    m_showProgramAct->setStatusTip(tr("Show the code (programming) view"));
++	    connect(m_showProgramAct, SIGNAL(triggered()), this, SLOT(showProgramView()));
++        QList<QAction *> viewMenuActions;
++        viewMenuActions << m_showBreadboardAct << m_showSchematicAct << m_showPCBAct << m_showProgramAct;
++        m_programView->initViewMenu(viewMenuActions);
++    }
++
++	m_showPartsBinIconViewAct = new QAction(tr("Show Parts Bin Icon View"), this);
++	m_showPartsBinIconViewAct->setStatusTip(tr("Display the parts bin in an icon view"));
++	connect(m_showPartsBinIconViewAct, SIGNAL(triggered()), this, SLOT(showPartsBinIconView()));
++
++	m_showPartsBinListViewAct = new QAction(tr("Show Parts Bin List View"), this);
++	m_showPartsBinListViewAct->setStatusTip(tr("Display the parts bin in a list view"));
++	connect(m_showPartsBinListViewAct, SIGNAL(triggered()), this, SLOT(showPartsBinListView()));
++
++	m_showAllLayersAct = new QAction(tr("&Show All Layers"), this);
++	m_showAllLayersAct->setStatusTip(tr("Show all the available layers for the current view"));
++	connect(m_showAllLayersAct, SIGNAL(triggered()), this, SLOT(showAllLayers()));
++
++	m_hideAllLayersAct = new QAction(tr("&Hide All Layers"), this);
++	m_hideAllLayersAct->setStatusTip(tr("Hide all the layers of the current view"));
++	connect(m_hideAllLayersAct, SIGNAL(triggered()), this, SLOT(hideAllLayers()));
++
++}
++
++void MainWindow::createWindowMenuActions() {
++	m_minimizeAct = new QAction(tr("&Minimize"), this);
++	m_minimizeAct->setShortcut(tr("Ctrl+M"));
++	m_minimizeAct->setStatusTip(tr("Minimize current window"));
++	connect(m_minimizeAct, SIGNAL(triggered(bool)), this, SLOT(minimize()));
++
++	/*
++	m_toggleToolbarAct = new QAction(tr("&Toolbar"), this);
++	m_toggleToolbarAct->setShortcut(tr("Shift+Ctrl+T"));
++	m_toggleToolbarAct->setCheckable(true);
++	m_toggleToolbarAct->setChecked(true);
++	m_toggleToolbarAct->setStatusTip(tr("Toggle Toolbar visibility"));
++	connect(m_toggleToolbarAct, SIGNAL(triggered(bool)), this, SLOT(toggleToolbar(bool)));
++	*/
++
++    m_toggleDebuggerOutputAct = new QAction(tr("Debugger Output"), this);
++    m_toggleDebuggerOutputAct->setCheckable(true);
++   	connect(m_toggleDebuggerOutputAct, SIGNAL(triggered(bool)), this, SLOT(toggleDebuggerOutput(bool)));
++}
++
++void MainWindow::createHelpMenuActions() {
++	m_openHelpAct = new QAction(tr("Online Tutorials"), this);
++	m_openHelpAct->setShortcut(tr("Ctrl+?"));
++	m_openHelpAct->setStatusTip(tr("Open Fritzing help"));
++	connect(m_openHelpAct, SIGNAL(triggered(bool)), this, SLOT(openHelp()));
++
++	m_openDonateAct = new QAction(tr("Donate to Fritzing"), this);
++	m_openDonateAct->setStatusTip(tr("Open Fritzing donation web page"));
++	connect(m_openDonateAct, SIGNAL(triggered(bool)), this, SLOT(openDonate()));
++
++	m_examplesAct = new QAction(tr("Online Projects Gallery"), this);
++	m_examplesAct->setStatusTip(tr("Open Fritzing examples"));
++	connect(m_examplesAct, SIGNAL(triggered(bool)), this, SLOT(openExamples()));
++
++	m_partsRefAct = new QAction(tr("Online Parts Reference"), this);
++	m_partsRefAct->setStatusTip(tr("Open Parts Reference"));
++	connect(m_partsRefAct, SIGNAL(triggered(bool)), this, SLOT(openPartsReference()));
++
++	m_showInViewHelpAct = new QAction(tr("First Time Help"), this);
++	m_showInViewHelpAct->setStatusTip(tr("Show or Hide First Time Help"));
++	m_showInViewHelpAct->setCheckable(true);
++	m_showInViewHelpAct->setChecked(true);
++	connect(m_showInViewHelpAct, SIGNAL(triggered(bool)), this, SLOT(showInViewHelp()));
++
++	/*m_visitFritzingDotOrgAct = new QAction(tr("Visit fritzing.org"), this);
++	m_visitFritzingDotOrgAct->setStatusTip(tr("www.fritzing.org"));
++	connect(m_visitFritzingDotOrgAct, SIGNAL(triggered(bool)), this, SLOT(visitFritzingDotOrg()));*/
++
++	m_checkForUpdatesAct = new QAction(tr("Check for updates..."), this);
++	m_checkForUpdatesAct->setStatusTip(tr("Check whether a newer version of Fritzing is available for download"));
++	connect(m_checkForUpdatesAct, SIGNAL(triggered()), QApplication::instance(), SLOT(checkForUpdates()));
++
++	m_aboutAct = new QAction(tr("&About"), this);
++	m_aboutAct->setStatusTip(tr("Show the application's about box"));
++	connect(m_aboutAct, SIGNAL(triggered()), this, SLOT(about()));
++	m_aboutAct->setMenuRole(QAction::AboutRole);
++
++	m_tipsAndTricksAct = new QAction(tr("Tips, Tricks and Shortcuts"), this);
++	m_tipsAndTricksAct->setStatusTip(tr("Display some handy Fritzing tips and tricks"));
++	connect(m_tipsAndTricksAct, SIGNAL(triggered()), this, SLOT(tipsAndTricks()));
++
++	m_aboutQtAct = new QAction(tr("&About Qt"), this);
++	m_aboutQtAct->setStatusTip(tr("Show Qt's about box"));
++	connect(m_aboutQtAct, SIGNAL(triggered()), qApp, SLOT(aboutQt()));
++
++	m_reportBugAct = new QAction(tr("Report a bug..."), this);
++	m_reportBugAct->setStatusTip(tr("Report a but you've found in Fritzing"));
++	connect(m_reportBugAct, SIGNAL(triggered()), this, SLOT(reportBug()));
++
++	m_enableDebugAct = new QAction(tr("Enable debugging log"), this);
++	m_enableDebugAct->setStatusTip(tr("Report a but you've found in Fritzing"));
++	m_enableDebugAct->setCheckable(true);
++	m_enableDebugAct->setChecked(DebugDialog::enabled());
++	connect(m_enableDebugAct, SIGNAL(triggered()), this, SLOT(enableDebug()));
++
++	m_importFilesFromPrevInstallAct = new QAction(tr("&Import parts and bins from old version..."), this);
++	m_importFilesFromPrevInstallAct->setStatusTip(tr("Import parts and bins from previous installation"));
++	connect(m_importFilesFromPrevInstallAct, SIGNAL(triggered()), this, SLOT(importFilesFromPrevInstall()));
++
++	m_partsEditorHelpAct = new QAction(tr("Parts Editor Help"), this);
++	m_partsEditorHelpAct->setStatusTip(tr("Display Parts Editor help in a browser"));
++	connect(m_partsEditorHelpAct, SIGNAL(triggered(bool)), this, SLOT(partsEditorHelp()));
++
++
++}
++
++void MainWindow::createMenus()
++{
++    createFileMenu();
++    createEditMenu();
++    createPartMenu();
++    createViewMenu();
++    createWindowMenu();
++    createTraceMenus();
++    createHelpMenu();
++}
++
++void MainWindow::createFileMenu() {
++    m_fileMenu = menuBar()->addMenu(tr("&File"));
++    m_fileMenu->addAction(m_newAct);
++    m_fileMenu->addAction(m_openAct);
++    m_fileMenu->addAction(m_revertAct);
++    m_fileMenu->addMenu(m_openRecentFileMenu);
++    m_fileMenu->addMenu(m_openExampleMenu);
++
++    m_fileMenu->addSeparator();
++    m_fileMenu->addAction(m_closeAct);
++    m_fileMenu->addAction(m_saveAct);
++    m_fileMenu->addAction(m_saveAsAct);
++    m_fileMenu->addAction(m_shareOnlineAct);
++
++	if (m_orderFabEnabled) {
++		m_fileMenu->addAction(m_orderFabAct);
++	}
++
++    m_fileMenu->addSeparator();
++	m_exportMenu = m_fileMenu->addMenu(tr("&Export"));
++    //m_fileMenu->addAction(m_pageSetupAct);
++    m_fileMenu->addAction(m_printAct);
++
++	QString name;
++	QString path;
++	QStringList args;
++	if (externalProcess(name, path, args)) {
++		m_fileMenu->addSeparator();
++		m_fileMenu->addAction(m_launchExternalProcessAct);
++	}
++
++#ifndef QT_NO_DEBUG
++    m_fileMenu->addSeparator();
++    m_fileMenu->addAction(m_exceptionAct);
++#endif
++
++	m_fileMenu->addSeparator();
++	m_fileMenu->addAction(m_quitAct);
++    connect(m_fileMenu, SIGNAL(aboutToShow()), this, SLOT(updateFileMenu()));
++
++	populateExportMenu();
++
++	m_exportMenu->addAction(m_exportBomAct);
++	m_exportMenu->addAction(m_exportNetlistAct);
++	//m_exportMenu->addAction(m_exportSpiceNetlistAct);
++
++	//m_exportMenu->addAction(m_exportEagleAct);
++}
++
++void MainWindow::populateExportMenu() {
++	QMenu * imageMenu = m_exportMenu->addMenu(tr("as Image"));
++	imageMenu->addAction(m_exportPngAct);
++	imageMenu->addAction(m_exportJpgAct);
++	imageMenu->addSeparator();
++	imageMenu->addAction(m_exportSvgAct);
++	imageMenu->addAction(m_exportPdfAct);
++	imageMenu->addAction(m_exportPsAct);
++
++	QMenu * productionMenu = m_exportMenu->addMenu(tr("for Production"));
++	productionMenu->addAction(m_exportEtchablePdfAct);
++	productionMenu->addAction(m_exportEtchableSvgAct);
++	productionMenu->addSeparator();
++	productionMenu->addAction(m_exportGerberAct);
++}
++
++
++void MainWindow::createEditMenu()
++{
++    m_editMenu = menuBar()->addMenu(tr("&Edit"));
++    m_editMenu->addAction(m_undoAct);
++    m_editMenu->addAction(m_redoAct);
++    m_editMenu->addSeparator();
++    m_editMenu->addAction(m_cutAct);
++    m_editMenu->addAction(m_copyAct);
++    m_editMenu->addAction(m_pasteAct);
++    m_editMenu->addAction(m_pasteInPlaceAct);
++    m_editMenu->addAction(m_duplicateAct);
++    m_editMenu->addAction(m_deleteAct);
++    m_editMenu->addAction(m_deleteMinusAct);
++    m_editMenu->addSeparator();
++    m_editMenu->addAction(m_selectAllAct);
++    m_editMenu->addAction(m_deselectAct);
++    m_editMenu->addSeparator();
++    m_editMenu->addAction(m_addNoteAct);
++    m_editMenu->addSeparator();
++    m_editMenu->addAction(m_preferencesAct);
++    updateEditMenu();
++    connect(m_editMenu, SIGNAL(aboutToShow()), this, SLOT(updateEditMenu()));
++}
++
++void MainWindow::createPartMenu() {
++    m_partMenu = menuBar()->addMenu(tr("&Part"));
++    connect(m_partMenu, SIGNAL(aboutToShow()), this, SLOT(updatePartMenu()));
++
++	m_partMenu->addAction(m_openInPartsEditorNewAct);
++	m_partMenu->addSeparator();
++
++    m_partMenu->addAction(m_saveBundledPart);
++
++	m_partMenu->addSeparator();
++	m_partMenu->addAction(m_flipHorizontalAct);
++	m_partMenu->addAction(m_flipVerticalAct);
++	m_rotateMenu = m_partMenu->addMenu(tr("Rotate"));
++	m_zOrderMenu = m_partMenu->addMenu(tr("Raise and Lower"));
++	m_zOrderWireMenu = new QMenu(m_zOrderMenu);
++	m_zOrderWireMenu->setTitle(m_zOrderMenu->title());
++    m_alignMenu = m_partMenu->addMenu(tr("Align"));
++	m_partMenu->addAction(m_moveLockAct);
++	m_partMenu->addAction(m_stickyAct);
++	m_partMenu->addAction(m_selectMoveLockAct);
++
++	
++	m_partMenu->addSeparator();
++	m_partMenu->addMenu(m_addToBinMenu);
++	m_partMenu->addAction(m_showPartLabelAct);
++	m_partMenu->addSeparator();
++	m_partMenu->addAction(m_selectAllObsoleteAct);
++	m_partMenu->addAction(m_swapObsoleteAct);
++
++	m_partMenu->addSeparator();
++	m_partMenu->addAction(m_findPartInSketchAct);
++
++	m_rotateMenu->addAction(m_rotate45cwAct);
++	m_rotateMenu->addAction(m_rotate90cwAct);
++	m_rotateMenu->addAction(m_rotate180Act);
++	m_rotateMenu->addAction(m_rotate90ccwAct);
++	m_rotateMenu->addAction(m_rotate45ccwAct);
++
++	m_zOrderMenu->addAction(m_bringToFrontAct);
++	m_zOrderMenu->addAction(m_bringForwardAct);
++	m_zOrderMenu->addAction(m_sendBackwardAct);
++	m_zOrderMenu->addAction(m_sendToBackAct);
++
++	m_zOrderWireMenu->addAction(m_bringToFrontWireAct);
++	m_zOrderWireMenu->addAction(m_bringForwardWireAct);
++	m_zOrderWireMenu->addAction(m_sendBackwardWireAct);
++	m_zOrderWireMenu->addAction(m_sendToBackWireAct);
++
++	m_alignMenu->addAction(m_alignLeftAct);
++	m_alignMenu->addAction(m_alignHorizontalCenterAct);
++	m_alignMenu->addAction(m_alignRightAct);    
++    m_alignMenu->addAction(m_alignTopAct);
++	m_alignMenu->addAction(m_alignVerticalCenterAct);
++	m_alignMenu->addAction(m_alignBottomAct);
++}
++
++void MainWindow::createViewMenu()
++{
++    m_viewMenu = menuBar()->addMenu(tr("&View"));
++    m_viewMenu->addAction(m_zoomInAct);
++    m_viewMenu->addAction(m_zoomOutAct);
++    m_viewMenu->addAction(m_fitInWindowAct);
++    m_viewMenu->addAction(m_actualSizeAct);
++    m_viewMenu->addAction(m_100PercentSizeAct);
++	m_viewMenu->addSeparator();
++
++    m_viewMenu->addAction(m_alignToGridAct);
++    m_viewMenu->addAction(m_showGridAct);
++    m_viewMenu->addAction(m_setGridSizeAct);
++    m_viewMenu->addAction(m_setBackgroundColorAct);
++	m_viewMenu->addSeparator();
++
++    m_viewMenu->addAction(m_showBreadboardAct);
++    m_viewMenu->addAction(m_showSchematicAct);
++    m_viewMenu->addAction(m_showPCBAct);
++    if (m_programView) m_viewMenu->addAction(m_showProgramAct);
++    m_viewMenu->addSeparator();
++    if (m_binManager) {
++        m_viewMenu->addAction(m_showPartsBinIconViewAct);
++        m_viewMenu->addAction(m_showPartsBinListViewAct);
++        m_viewMenu->addSeparator();
++    }
++    connect(m_viewMenu, SIGNAL(aboutToShow()), this, SLOT(updateLayerMenu()));
++    m_numFixedActionsInViewMenu = m_viewMenu->actions().size();
++}
++
++void MainWindow::createWindowMenu() {
++    m_windowMenu = menuBar()->addMenu(tr("&Window"));
++	m_windowMenu->addAction(m_minimizeAct);
++	m_windowMenu->addSeparator();
++	//m_windowMenu->addAction(m_toggleToolbarAct);
++	updateWindowMenu();
++	connect(m_windowMenu, SIGNAL(aboutToShow()), this, SLOT(updateWindowMenu()));
++}
++
++void MainWindow::createTraceMenus()
++{
++	m_pcbTraceMenu = menuBar()->addMenu(tr("&Routing"));
++	m_pcbTraceMenu->addAction(m_newAutorouteAct);
++	m_pcbTraceMenu->addAction(m_newDesignRulesCheckAct);
++	m_pcbTraceMenu->addAction(m_autorouterSettingsAct);
++	m_pcbTraceMenu->addAction(m_fabQuoteAct);
++
++	QMenu * groundFillMenu = m_pcbTraceMenu->addMenu(tr("Ground Fill"));
++
++	groundFillMenu->addAction(m_copperFillAct);
++	groundFillMenu->addAction(m_groundFillAct);
++	groundFillMenu->addAction(m_removeGroundFillAct);
++	groundFillMenu->addAction(m_setGroundFillSeedsAct);
++	groundFillMenu->addAction(m_clearGroundFillSeedsAct);
++	groundFillMenu->addAction(m_setGroundFillKeepoutAct);
++	//m_pcbTraceMenu->addAction(m_updateRoutingStatusAct);
++	m_pcbTraceMenu->addSeparator();
++
++	m_pcbTraceMenu->addAction(m_viewFromBelowToggleAct);
++	m_pcbTraceMenu->addAction(m_activeLayerBothAct);
++	m_pcbTraceMenu->addAction(m_activeLayerBottomAct);
++	m_pcbTraceMenu->addAction(m_activeLayerTopAct);
++	m_pcbTraceMenu->addSeparator();
++
++	m_pcbTraceMenu->addAction(m_changeTraceLayerAct);
++	m_pcbTraceMenu->addAction(m_excludeFromAutorouteAct);
++	m_pcbTraceMenu->addSeparator();
++
++	m_pcbTraceMenu->addAction(m_showUnroutedAct);
++	m_pcbTraceMenu->addAction(m_selectAllTracesAct);
++	m_pcbTraceMenu->addAction(m_selectAllExcludedTracesAct);
++	m_pcbTraceMenu->addAction(m_selectAllIncludedTracesAct);
++	m_pcbTraceMenu->addAction(m_selectAllJumperItemsAct);
++	m_pcbTraceMenu->addAction(m_selectAllViasAct);
++	m_pcbTraceMenu->addAction(m_selectAllCopperFillAct);
++
++    //m_pcbTraceMenu->addSeparator();
++	//m_pcbTraceMenu->addAction(m_checkLoadedTracesAct);
++
++    m_schematicTraceMenu = menuBar()->addMenu(tr("&Routing"));
++	m_schematicTraceMenu->addAction(m_newAutorouteAct);
++	m_schematicTraceMenu->addAction(m_excludeFromAutorouteAct);
++	m_schematicTraceMenu->addAction(m_showUnroutedAct);
++	m_schematicTraceMenu->addAction(m_selectAllTracesAct);
++	m_schematicTraceMenu->addAction(m_selectAllExcludedTracesAct);
++	m_schematicTraceMenu->addAction(m_selectAllIncludedTracesAct);
++	//m_schematicTraceMenu->addAction(m_updateRoutingStatusAct);
++
++#ifndef QT_NO_DEBUG
++	m_schematicTraceMenu->addAction(m_tidyWiresAct);
++#endif
++
++	m_breadboardTraceMenu = menuBar()->addMenu(tr("&Routing"));
++	m_breadboardTraceMenu->addAction(m_showUnroutedAct);
++	m_breadboardTraceMenu->addAction(m_selectAllWiresAct);
++
++	updateTraceMenu();
++	connect(m_pcbTraceMenu, SIGNAL(aboutToShow()), this, SLOT(updateTraceMenu()));
++	connect(m_schematicTraceMenu, SIGNAL(aboutToShow()), this, SLOT(updateTraceMenu()));
++	connect(m_breadboardTraceMenu, SIGNAL(aboutToShow()), this, SLOT(updateTraceMenu()));
++
++    menuBar()->addSeparator();
++}
++
++void MainWindow::createHelpMenu()
++{
++    m_helpMenu = menuBar()->addMenu(tr("&Help"));
++    m_helpMenu->addAction(m_showInViewHelpAct);
++    m_helpMenu->addAction(m_openHelpAct);
++    m_helpMenu->addAction(m_examplesAct);
++    m_helpMenu->addAction(m_partsRefAct);
++	m_helpMenu->addSeparator();
++    m_helpMenu->addAction(m_partsEditorHelpAct);
++	m_helpMenu->addSeparator();
++	m_helpMenu->addAction(m_checkForUpdatesAct);
++	m_helpMenu->addAction(m_importFilesFromPrevInstallAct);
++	m_helpMenu->addSeparator();
++	m_helpMenu->addAction(m_reportBugAct);
++	m_helpMenu->addAction(m_enableDebugAct);
++	m_helpMenu->addSeparator();
++	m_helpMenu->addAction(m_aboutAct);
++    m_helpMenu->addAction(m_openDonateAct);
++	m_helpMenu->addAction(m_tipsAndTricksAct);
++#ifndef QT_NO_DEBUG
++	m_helpMenu->addAction(m_aboutQtAct);
++#endif
++}
++
++
++void MainWindow::updateLayerMenu(bool resetLayout) {
++    if (m_viewMenu == NULL) return;
++    if (m_showAllLayersAct == NULL) return;
++
++	QList<QAction *> actions;
++
++    if (m_showPartsBinIconViewAct) {
++	    if (m_binManager) {
++		    m_showPartsBinIconViewAct->setEnabled(true);
++		    m_showPartsBinListViewAct->setEnabled(true);
++		    actions << m_showPartsBinIconViewAct << m_showPartsBinListViewAct;
++		    setActionsIcons(m_binManager->currentViewIsIconView() ? 0 : 1, actions);
++	    }
++	    else {
++		    m_showPartsBinIconViewAct->setEnabled(false);
++		    m_showPartsBinListViewAct->setEnabled(false);
++	    }
++    }
++
++	removeActionsStartingAt(m_viewMenu, m_numFixedActionsInViewMenu);
++    if (m_showAllLayersAct) m_viewMenu->addAction(m_showAllLayersAct);
++    if (m_hideAllLayersAct) m_viewMenu->addAction(m_hideAllLayersAct);
++
++	if (m_currentGraphicsView == NULL) return;
++
++	m_alignToGridAct->setChecked(m_currentGraphicsView->alignedToGrid());
++	m_showGridAct->setChecked(m_currentGraphicsView->showingGrid());
++	
++	LayerHash viewLayers = m_currentGraphicsView->viewLayers();
++	LayerList keys = viewLayers.keys();
++
++	// make sure they're in ascending order when inserting into the menu
++	qSort(keys.begin(), keys.end());
++
++	foreach (ViewLayer::ViewLayerID key, keys) {
++		ViewLayer * viewLayer = viewLayers.value(key);
++		//DebugDialog::debug(QString("Layer: %1 is %2").arg(viewLayer->action()->text()).arg(viewLayer->action()->isEnabled()));
++    	if (viewLayer != NULL) {
++			if (viewLayer->parentLayer()) continue;
++			m_viewMenu->addAction(viewLayer->action());
++			disconnect(viewLayer->action(), SIGNAL(triggered()), this, SLOT(updateLayerMenu()));
++			connect(viewLayer->action(), SIGNAL(triggered()), this, SLOT(updateLayerMenu()));
++		}
++	}
++
++
++	m_hideAllLayersAct->setEnabled(false);
++	m_showAllLayersAct->setEnabled(false);
++
++	if (keys.count() <= 0) return;
++
++	ViewLayer *prev = viewLayers.value(keys[0]);
++	if (prev == NULL) {
++		// jrc: I think prev == NULL is actually a side effect from an earlier bug
++		// but I haven't figured out the cause yet
++		// at any rate, when this bug occurs, keys[0] is some big negative number that looks like an
++		// uninitialized or scrambled layerID
++		DebugDialog::debug(QString("updateAllLayersActions keys[0] failed %1").arg(keys[0]) );
++		return;
++	}
++
++	bool sameState = prev->action()->isChecked();
++	bool checked = prev->action()->isChecked();
++	//DebugDialog::debug(QString("Layer: %1 is %2").arg(prev->action()->text()).arg(prev->action()->isChecked()));
++	for (int i = 1; i < keys.count(); i++) {
++		ViewLayer *viewLayer = viewLayers.value(keys[i]);
++		//DebugDialog::debug(QString("Layer: %1 is %2").arg(viewLayer->action()->text()).arg(viewLayer->action()->isChecked()));
++		if (viewLayer != NULL) {
++			if (prev != NULL && prev->action()->isChecked() != viewLayer->action()->isChecked() ) {
++				// if the actions aren't all checked or unchecked I don't bother about the "checked" variable
++				sameState = false;
++				break;
++			} 
++			else {
++				sameState = true;
++				checked = viewLayer->action()->isChecked();
++			}
++			prev = viewLayer;
++		}
++	}
++
++	//DebugDialog::debug(QString("sameState: %1").arg(sameState));
++	//DebugDialog::debug(QString("checked: %1").arg(checked));
++	if (sameState) {
++		if(checked) {
++			m_hideAllLayersAct->setEnabled(true);
++		} 
++		else {
++			m_showAllLayersAct->setEnabled(true);
++		}
++	} 
++	else {
++		m_showAllLayersAct->setEnabled(true);
++		m_hideAllLayersAct->setEnabled(true);
++	}
++
++	if (resetLayout) {
++		m_layerPalette->resetLayout(viewLayers, keys);
++	}
++	m_layerPalette->updateLayerPalette(viewLayers, keys);
++}
++
++void MainWindow::updateWireMenu() {
++	// assumes update wire menu is only called when right-clicking a wire
++	// and that wire is cached by the menu in Wire::mousePressEvent
++
++	Wire * wire = m_activeWire;
++	m_activeWire = NULL;
++
++	if (wire) {
++		enableAddBendpointAct(wire);
++	}
++
++	bool enableAll = true;
++	bool deleteOK = false;
++	bool createTraceOK = false;
++	bool excludeOK = false;
++	bool enableZOK = true;
++	bool gotRat = false;
++	bool ctlOK = false;
++
++	if (wire != NULL) {
++		
++		if (wire->getRatsnest()) {
++			QList<ConnectorItem *> ends;
++			Wire * jt = wire->findTraced(m_currentGraphicsView->getTraceFlag(), ends);
++			createTraceOK = (jt == NULL) || (!jt->getTrace());
++			deleteOK = true;
++			gotRat = true;
++			enableZOK = false;
++		}
++		else if (wire->getTrace()) {
++			deleteOK = true;
++			excludeOK = true;
++			m_excludeFromAutorouteWireAct->setChecked(!wire->getAutoroutable());
++			if (m_currentGraphicsView == m_pcbGraphicsView && m_currentGraphicsView->boardLayers() > 1) {
++				if (wire->canSwitchLayers()) {
++                    if (ViewLayer::topLayers().contains(wire->viewLayerID())) {
++                        m_changeTraceLayerWireAct->setText(tr("Move to bottom layer"));
++                    }
++                    else {
++                        m_changeTraceLayerWireAct->setText(tr("Move to top layer"));
++                    }
++					ctlOK = true;
++				}
++			}
++
++		}
++		else {
++			deleteOK = true;
++		}
++	}
++
++
++    QMenu* wireColorMenu = (m_currentGraphicsView == m_breadboardGraphicsView ? m_breadboardWireColorMenu : m_schematicWireColorMenu);
++	if (wire) {
++		wireColorMenu->setEnabled(true);
++        QString colorString = wire->colorString();
++        //DebugDialog::debug("wire colorstring " + colorString);
++		foreach (QAction * action, wireColorMenu->actions()) {
++			QString colorName = action->data().toString();
++            //DebugDialog::debug("colorname " + colorName);
++			action->setChecked(colorName.compare(colorString) == 0);
++		}
++	}
++	else {
++		wireColorMenu->setEnabled(false);
++	}
++
++	m_bringToFrontWireAct->setWire(wire);
++	m_bringForwardWireAct->setWire(wire);
++	m_sendBackwardWireAct->setWire(wire);
++	m_sendToBackWireAct->setWire(wire);
++	m_createTraceWireAct->setWire(wire);
++	m_createWireWireAct->setWire(wire);
++	m_deleteWireAct->setWire(wire);
++	m_deleteWireMinusAct->setWire(wire);
++	m_excludeFromAutorouteWireAct->setWire(wire);
++	m_changeTraceLayerWireAct->setWire(wire);
++
++	m_bringToFrontWireAct->setEnabled(enableZOK);
++	m_bringForwardWireAct->setEnabled(enableZOK);
++	m_sendBackwardWireAct->setEnabled(enableZOK);
++	m_sendToBackWireAct->setEnabled(enableZOK);
++	m_createTraceWireAct->setEnabled(enableAll && createTraceOK);
++	m_createWireWireAct->setEnabled(enableAll && createTraceOK);
++	m_deleteWireAct->setEnabled(enableAll && deleteOK);
++	m_deleteWireMinusAct->setEnabled(enableAll && deleteOK && !gotRat);
++	m_excludeFromAutorouteWireAct->setEnabled(enableAll && excludeOK);
++	m_changeTraceLayerAct->setEnabled(ctlOK);
++	m_changeTraceLayerWireAct->setEnabled(ctlOK);
++
++	if (gotRat) {
++		m_deleteWireAct->setText(tr("Delete Ratsnest Line"));
++	}
++	else {
++		m_deleteWireAct->setText(tr("Delete Wire"));
++	}
++
++
++}
++
++void MainWindow::updatePartMenu() {
++	if (m_currentGraphicsView == NULL) return;
++	if (m_partMenu == NULL) return;
++
++	ItemCount itemCount = m_currentGraphicsView->calcItemCount();
++
++	bool enable = true;
++	bool zenable = true;
++
++	if (itemCount.selCount <= 0) {
++		zenable = enable = false;
++	}
++	else {
++		if (itemCount.itemsCount == itemCount.selCount) {
++			// if all items are selected
++			// z-reordering is a no-op
++			zenable = false;
++		}
++	}
++
++    m_alignLeftAct->setEnabled(itemCount.selCount - itemCount.wireCount > 1);
++    m_alignRightAct->setEnabled(itemCount.selCount - itemCount.wireCount > 1);
++    m_alignTopAct->setEnabled(itemCount.selCount - itemCount.wireCount > 1);
++    m_alignBottomAct->setEnabled(itemCount.selCount - itemCount.wireCount > 1);
++    m_alignVerticalCenterAct->setEnabled(itemCount.selCount - itemCount.wireCount > 1);
++    m_alignHorizontalCenterAct->setEnabled(itemCount.selCount - itemCount.wireCount > 1);
++
++	//DebugDialog::debug(QString("enable layer actions %1").arg(enable));
++	m_bringToFrontAct->setEnabled(zenable);
++	m_bringForwardAct->setEnabled(zenable);
++	m_sendBackwardAct->setEnabled(zenable);
++	m_sendToBackAct->setEnabled(zenable);
++    
++	m_moveLockAct->setEnabled(itemCount.selCount > 0 && itemCount.selCount > itemCount.wireCount);
++	m_moveLockAct->setChecked(itemCount.moveLockCount > 0);
++	m_selectMoveLockAct->setEnabled(true);
++
++	m_showPartLabelAct->setEnabled((itemCount.hasLabelCount > 0) && enable);
++	m_showPartLabelAct->setText(itemCount.visLabelCount == itemCount.hasLabelCount ? tr("Hide part label") : tr("Show part label"));
++    m_showPartLabelAct->setData(itemCount.visLabelCount != itemCount.hasLabelCount);
++
++	bool renable = (itemCount.selRotatable > 0);
++	bool renable45 = (itemCount.sel45Rotatable > 0);
++
++	//DebugDialog::debug(QString("enable rotate (2) %1").arg(enable));
++
++	m_rotate90cwAct->setEnabled(renable && enable);
++	m_rotate180Act->setEnabled(renable && enable);
++	m_rotate90ccwAct->setEnabled(renable && enable);
++	m_rotate45ccwAct->setEnabled(renable && renable45 && enable);
++	m_rotate45cwAct->setEnabled(renable && renable45 && enable);
++
++	m_flipHorizontalAct->setEnabled(enable && (itemCount.selHFlipable > 0) && (m_currentGraphicsView != m_pcbGraphicsView));
++	m_flipVerticalAct->setEnabled(enable && (itemCount.selVFlipable > 0) && (m_currentGraphicsView != m_pcbGraphicsView));
++
++	updateItemMenu();
++	updateEditMenu();
++
++
++    bool ctbpVisible = false;
++    bool ctbpEnabled = false;
++	if (itemCount.selCount == 1) {
++        ItemBase * itemBase = dynamic_cast<ItemBase *>(m_currentGraphicsView->scene()->selectedItems()[0]);
++		enableAddBendpointAct(itemBase);
++
++        Via * via = qobject_cast<Via *>(itemBase->layerKinChief());
++        if (via) {
++            ctbpVisible = true;
++            int count = 0;
++            QList<ConnectorItem *> viaConnectorItems;
++            viaConnectorItems << via->connectorItem();
++            if (via->connectorItem()->getCrossLayerConnectorItem()) {
++                viaConnectorItems << via->connectorItem()->getCrossLayerConnectorItem();
++            }
++
++            foreach (ConnectorItem * viaConnectorItem, viaConnectorItems) {
++                foreach (ConnectorItem * connectorItem, viaConnectorItem->connectedToItems()) {
++                    Wire * wire = qobject_cast<Wire *>(connectorItem->attachedTo());
++                    if (wire == NULL) continue;
++                    if (wire->getRatsnest()) continue;
++
++                    if (wire->isTraceType(m_currentGraphicsView->getTraceFlag())) {
++                        count++;
++                        if (count > 1) { 
++                            ctbpEnabled = true;
++                            break;
++                        }
++                    }
++                }
++                if (count > 1) break;
++            }
++        }
++
++
++		m_openInPartsEditorNewAct->setEnabled(itemBase->canEditPart());
++        m_stickyAct->setVisible(itemBase->isBaseSticky());
++	    m_stickyAct->setEnabled(true);
++	    m_stickyAct->setChecked(itemBase->isBaseSticky() && itemBase->isLocalSticky());
++
++        QList<ItemBase *> itemBases;
++        itemBases.append(itemBase);
++        itemBases.append(itemBase->layerKinChief()->layerKin());
++        bool hpsa = false;
++        foreach (ItemBase * lkpi, itemBases) {
++            if (lkpi->viewLayerID() == ViewLayer::Silkscreen1 || lkpi->viewLayerID() == ViewLayer::Silkscreen0) {
++                hpsa = true;
++                m_hidePartSilkscreenAct->setText(lkpi->layerHidden() ? tr("Show part silkscreen") : tr("Hide part silkscreen"));
++                break;
++            }
++        }
++
++        m_hidePartSilkscreenAct->setEnabled(hpsa);
++	}
++    else {
++        m_hidePartSilkscreenAct->setEnabled(false);
++        m_stickyAct->setVisible(false);
++		m_openInPartsEditorNewAct->setEnabled(false);
++    }
++    m_convertToBendpointAct->setEnabled(ctbpEnabled);
++    m_convertToBendpointAct->setVisible(ctbpVisible);
++    m_convertToBendpointSeparator->setVisible(ctbpVisible);
++
++	// TODO: only enable if there is an obsolete part in the sketch
++	m_selectAllObsoleteAct->setEnabled(true);
++	m_swapObsoleteAct->setEnabled(itemCount.obsoleteCount > 0);
++    m_findPartInSketchAct->setEnabled(m_currentGraphicsView != NULL);
++	m_openProgramWindowAct->setEnabled(true);
++}
++
++void MainWindow::updateTransformationActions() {
++    // update buttons in sketch toolbar at bottom
++
++	if (m_currentGraphicsView == NULL) return;
++    if (m_rotate90cwAct == NULL) return;
++
++	ItemCount itemCount = m_currentGraphicsView->calcItemCount();
++	bool enable = (itemCount.selRotatable > 0);
++    bool renable = (itemCount.sel45Rotatable > 0);
++
++	//DebugDialog::debug(QString("enable rotate (1) %1").arg(enable));
++
++	m_rotate90cwAct->setEnabled(enable);
++	m_rotate180Act->setEnabled(enable);
++	m_rotate90ccwAct->setEnabled(enable);
++	m_rotate45ccwAct->setEnabled(enable && renable);
++	m_rotate45cwAct->setEnabled(enable && renable);
++	foreach(SketchToolButton* rotateButton, m_rotateButtons) {
++		rotateButton->setEnabled(enable);
++	}
++
++	m_flipHorizontalAct->setEnabled((itemCount.selHFlipable > 0) && (m_currentGraphicsView != m_pcbGraphicsView));
++	m_flipVerticalAct->setEnabled((itemCount.selVFlipable > 0) && (m_currentGraphicsView != m_pcbGraphicsView));
++
++	enable = m_flipHorizontalAct->isEnabled() || m_flipVerticalAct->isEnabled();
++	foreach(SketchToolButton* flipButton, m_flipButtons) {
++		flipButton->setEnabled(enable);
++	}
++}
++
++void MainWindow::updateItemMenu() {
++	if (m_currentGraphicsView == NULL) return;
++
++	ConnectorItem * activeConnectorItem = m_activeConnectorItem;
++	m_activeConnectorItem = NULL;
++
++	QList<QGraphicsItem *> items = m_currentGraphicsView->scene()->selectedItems();
++
++	int selCount = 0;
++	ItemBase * itemBase = NULL;
++	foreach(QGraphicsItem * item, items) {
++		ItemBase * ib = ItemBase::extractTopLevelItemBase(item);
++		if (ib == NULL) continue;
++
++		selCount++;
++		if (selCount == 1) itemBase = ib;
++		else if (selCount > 1) break;
++	}
++
++	PaletteItem *selected = qobject_cast<PaletteItem *>(itemBase);
++	bool enabled = (selCount == 1) && (selected != NULL);
++	m_addToBinMenu->setEnabled(enabled);
++	m_addToBinMenu->clear();
++	if(enabled) {
++		QList<QAction*> acts = m_binManager->openedBinsActions(selectedModuleID());
++		m_addToBinMenu->addActions(acts);
++	}
++
++	m_saveBundledPart->setEnabled(enabled && !selected->modelPart()->isCore());
++
++
++	// can't open wire in parts editor
++	enabled &= selected != NULL && itemBase != NULL && itemBase->canEditPart();
++
++	m_disconnectAllAct->setEnabled(enabled && m_currentGraphicsView->canDisconnectAll() && (itemBase->rightClickedConnector() != NULL));
++
++	bool gfsEnabled = false;
++	if (activeConnectorItem) {
++		if (activeConnectorItem->attachedToItemType() != ModelPart::CopperFill) {
++			gfsEnabled = true;
++			m_setOneGroundFillSeedAct->setChecked(activeConnectorItem->isGroundFillSeed());
++		}
++	}
++	m_setOneGroundFillSeedAct->setEnabled(gfsEnabled);
++	m_setOneGroundFillSeedAct->setConnectorItem(activeConnectorItem);
++}
++
++void MainWindow::updateEditMenu() {
++	QClipboard *clipboard = QApplication::clipboard();
++	m_pasteAct->setEnabled(false);
++	m_pasteInPlaceAct->setEnabled(false);
++	if (clipboard != NULL) {
++		const QMimeData *mimeData = clipboard->mimeData(QClipboard::Clipboard);
++		if (mimeData != NULL) {
++			if (mimeData->hasFormat("application/x-dnditemsdata")) {
++				m_pasteAct->setEnabled(true);
++				m_pasteInPlaceAct->setEnabled(true);
++				//DebugDialog::debug(QString("paste enabled: true"));
++			}
++		}
++	}
++
++	if (m_currentGraphicsView != NULL) {
++		const QList<QGraphicsItem *> items =  m_currentGraphicsView->scene()->selectedItems();
++		bool copyActsEnabled = false;
++		bool deleteActsEnabled = false;
++		foreach (QGraphicsItem * item, items) {
++			if (m_currentGraphicsView->canDeleteItem(item, items.count())) {
++				deleteActsEnabled = true;
++			}
++			if (m_currentGraphicsView->canCopyItem(item, items.count())) {
++				copyActsEnabled = true;
++			}
++		}
++
++		//DebugDialog::debug(QString("enable cut/copy/duplicate/delete %1 %2 %3").arg(copyActsEnabled).arg(deleteActsEnabled).arg(m_currentWidget->viewID()) );
++		m_deleteAct->setEnabled(deleteActsEnabled);
++		m_deleteMinusAct->setEnabled(deleteActsEnabled);
++		m_deleteAct->setText(tr("Delete"));
++		m_cutAct->setEnabled(deleteActsEnabled && copyActsEnabled);
++		m_copyAct->setEnabled(copyActsEnabled);
++		m_duplicateAct->setEnabled(copyActsEnabled);
++	}
++}
++
++void MainWindow::updateTraceMenu() {
++    if (m_pcbTraceMenu == NULL) return;
++
++	bool tEnabled = false;
++	bool twEnabled = false;
++	bool ctlEnabled = false;
++	bool arEnabled = false;
++
++    TraceMenuThing traceMenuThing;
++
++	if (m_currentGraphicsView != NULL) {
++		QList<QGraphicsItem *> items = m_currentGraphicsView->scene()->items();
++		foreach (QGraphicsItem * item, items) {
++			Wire * wire = dynamic_cast<Wire *>(item);
++			if (wire == NULL) {
++				if (m_currentGraphicsView == m_pcbGraphicsView) {
++                    updatePCBTraceMenu(item, traceMenuThing);
++                }
++                continue;
++			}
++
++			if (!wire->isEverVisible()) continue;
++			if (wire->getRatsnest()) {
++				//rEnabled = true;
++				//if (wire->isSelected()) {
++					//ctEnabled = true;
++				//}
++			}
++			else if (wire->isTraceType(m_currentGraphicsView->getTraceFlag())) {
++				arEnabled = true;
++				tEnabled = true;
++				twEnabled = true;
++				if (wire->isSelected()) {
++					traceMenuThing.exEnabled = true;
++					if (wire->getAutoroutable()) {
++						traceMenuThing.exChecked = false;
++					}
++				}
++				if (m_currentGraphicsView == m_pcbGraphicsView && m_currentGraphicsView->boardLayers() > 1) {
++					if (wire->canSwitchLayers()) {
++						ctlEnabled = true;
++					}
++				}
++			}
++		}
++	}
++
++	if (!arEnabled) {
++		if (m_currentGraphicsView != NULL) {
++			arEnabled = m_currentGraphicsView->hasAnyNets(); 
++		}
++	}
++
++    bool anyOrNo = (traceMenuThing.boardCount >= 1 || m_currentGraphicsView != m_pcbGraphicsView);
++
++	m_excludeFromAutorouteAct->setEnabled(traceMenuThing.exEnabled);
++	m_excludeFromAutorouteAct->setChecked(traceMenuThing.exChecked);
++	m_changeTraceLayerAct->setEnabled(ctlEnabled);
++	m_orderFabAct->setEnabled(traceMenuThing.boardCount > 0);
++	m_showUnroutedAct->setEnabled(true);
++	m_selectAllTracesAct->setEnabled(tEnabled && anyOrNo);
++	m_selectAllWiresAct->setEnabled(tEnabled && anyOrNo);
++	m_selectAllCopperFillAct->setEnabled(traceMenuThing.gfrEnabled && traceMenuThing.boardCount >= 1);
++	m_selectAllExcludedTracesAct->setEnabled(tEnabled && anyOrNo);
++	m_selectAllIncludedTracesAct->setEnabled(tEnabled && anyOrNo);
++	m_selectAllJumperItemsAct->setEnabled(traceMenuThing.jiEnabled && traceMenuThing.boardCount >= 1);
++	m_selectAllViasAct->setEnabled(traceMenuThing.viaEnabled && traceMenuThing.boardCount >= 1);
++	m_tidyWiresAct->setEnabled(twEnabled);
++
++    QString sides;
++    if (m_pcbGraphicsView->layerIsActive(ViewLayer::Copper0) && m_pcbGraphicsView->layerIsActive(ViewLayer::Copper1)) {
++        sides = tr("top and bottom");
++    }
++    else if (m_pcbGraphicsView->layerIsActive(ViewLayer::Copper0)) {
++        sides = tr("bottom");
++    }
++    else sides = tr("top");
++
++    QString groundFillString = tr("Ground Fill (%1)").arg(sides);
++    QString copperFillString = tr("Copper Fill (%1)").arg(sides);
++
++	m_groundFillAct->setEnabled(traceMenuThing.boardCount >= 1);
++    m_groundFillAct->setText(groundFillString);
++	m_copperFillAct->setEnabled(traceMenuThing.boardCount >= 1);
++	m_copperFillAct->setText(copperFillString);
++	m_removeGroundFillAct->setEnabled(traceMenuThing.gfrEnabled && traceMenuThing.boardCount >= 1);
++
++	// TODO: set and clear enabler logic
++	m_setGroundFillSeedsAct->setEnabled(traceMenuThing.gfsEnabled && traceMenuThing.boardCount >= 1);
++	m_clearGroundFillSeedsAct->setEnabled(traceMenuThing.gfsEnabled && traceMenuThing.boardCount >= 1);
++
++	m_newDesignRulesCheckAct->setEnabled(traceMenuThing.boardCount >= 1);
++	m_checkLoadedTracesAct->setEnabled(true);
++	m_autorouterSettingsAct->setEnabled(m_currentGraphicsView == m_pcbGraphicsView);
++	m_updateRoutingStatusAct->setEnabled(true);
++
++
++	m_fabQuoteAct->setEnabled(m_currentGraphicsView == m_pcbGraphicsView);
++}
++
++
++void MainWindow::updatePCBTraceMenu(QGraphicsItem * item, TraceMenuThing & traceMenuThing) 
++{
++	ItemBase * itemBase = dynamic_cast<ItemBase *>(item);
++	if (itemBase == NULL) return;
++	if (!itemBase->isEverVisible()) return;
++				
++	if (!traceMenuThing.gfsEnabled) {
++		traceMenuThing.gfsEnabled = itemBase->itemType() != ModelPart::CopperFill && itemBase->hasConnectors();
++	}
++
++    if (Board::isBoard(itemBase)) {
++        traceMenuThing.boardCount++;
++        if (itemBase->isSelected()) traceMenuThing.boardSelectedCount++;
++    }
++
++	switch (itemBase->itemType()) {
++		case ModelPart::Jumper:
++			traceMenuThing.jiEnabled = true;
++			if (itemBase->isSelected()) {
++				traceMenuThing.exEnabled = true;
++				if (qobject_cast<JumperItem *>(itemBase->layerKinChief())->getAutoroutable()) {
++					traceMenuThing.exChecked = false;
++				}
++			}
++			break;
++		case ModelPart::Via:
++			traceMenuThing.viaEnabled = true;
++			if (itemBase->isSelected()) {
++				traceMenuThing.exEnabled = true;
++				if (qobject_cast<Via *>(itemBase->layerKinChief())->getAutoroutable()) {
++					traceMenuThing.exChecked = false;
++				}
++			}
++			break;
++		case ModelPart::CopperFill:
++			traceMenuThing.gfrEnabled = true;
++		default:
++			break;
++	}
++}
++
++void MainWindow::zoomIn() {
++	m_zoomSlider->zoomIn();
++}
++
++void MainWindow::zoomOut() {
++	m_zoomSlider->zoomOut();
++}
++
++void MainWindow::fitInWindow() {
++	if (m_currentGraphicsView == NULL) return;
++
++	double newZoom = m_currentGraphicsView->fitInWindow();
++	m_zoomSlider->setValue(newZoom);
++}
++
++void MainWindow::hundredPercentSize() {
++	m_currentGraphicsView->absoluteZoom(100);
++	m_zoomSlider->setValue(100);
++}
++
++void MainWindow::actualSize() {
++	QMessageBox::information(this, tr("Actual Size"),
++				tr("It doesn't seem to be possible to automatically determine the actual physical size of the monitor, so "
++				"'actual size' as currently implemented is only a guess. "
++				"Your best bet would be to drag out a ruler part, then place a real (physical) ruler on top and zoom until they match up."
++				));
++
++
++	int dpi = this->physicalDpiX();
++	int l = this->logicalDpiX();
++
++	DebugDialog::debug(QString("actual size %1 %2").arg(dpi).arg(l));
++
++	// remember the parameter to the next two functions is a percent
++	m_currentGraphicsView->absoluteZoom(dpi * 100.0 / GraphicsUtils::SVGDPI);
++	m_zoomSlider->setValue(dpi * 100.0 / GraphicsUtils::SVGDPI);
++}
++
++void MainWindow::showBreadboardView() {
++	setCurrentTabIndex(0);
++}
++
++void MainWindow::showSchematicView() {
++	setCurrentTabIndex(1);
++}
++
++void MainWindow::showPCBView() {
++	setCurrentTabIndex(2);
++}
++
++void MainWindow::showProgramView() {
++	setCurrentTabIndex(3);
++}
++
++void MainWindow::setCurrentView(ViewLayer::ViewID viewID)
++{
++    if (viewID == ViewLayer::BreadboardView) showBreadboardView();
++    else if (viewID == ViewLayer::SchematicView) showSchematicView();
++    else if (viewID == ViewLayer::PCBView) showPCBView();
++}
++
++void MainWindow::showPartsBinIconView() {
++	if (m_binManager) m_binManager->toIconView();
++}
++
++void MainWindow::showPartsBinListView() {
++	if (m_binManager) m_binManager->toListView();
++}
++
++void MainWindow::openHelp() {
++	QDesktopServices::openUrl(QString("http://fritzing.org/learning/"));
++}
++
++void MainWindow::openDonate() {
++	QDesktopServices::openUrl(QString("http://fritzing.org/shop/donations/"));
++}
++
++void MainWindow::openExamples() {
++	QDesktopServices::openUrl(QString("http://fritzing.org/projects/"));
++}
++
++void MainWindow::openPartsReference() {
++	QDesktopServices::openUrl(QString("http://fritzing.org/parts/"));
++}
++
++void MainWindow::visitFritzingDotOrg() {
++	 QDesktopServices::openUrl(QString("http://www.fritzing.org"));
++}
++
++void MainWindow::reportBug() {
++	 QDesktopServices::openUrl(QString("http://code.google.com/p/fritzing/issues"));
++}
++
++void MainWindow::partsEditorHelp() {
++	QDir * dir = FolderUtils::getApplicationSubFolder("help");
++	QString path = dir->absoluteFilePath("parts_editor_help.html");
++	if (QFileInfo(path).exists()) {
++		QDesktopServices::openUrl(QString("file:///%1").arg(path));
++	}
++}
++
++
++
++void MainWindow::enableDebug() {
++	DebugDialog::setEnabled(m_enableDebugAct->isChecked());
++	if (!m_windowMenu->actions().contains(m_toggleDebuggerOutputAct)) {
++	    m_windowMenu->insertSeparator(m_windowMenuSeparator);
++		m_windowMenu->insertAction(m_windowMenuSeparator, m_toggleDebuggerOutputAct);
++		toggleDebuggerOutput(true);
++	}
++}
++
++
++void MainWindow::openNewPartsEditor(PaletteItem * paletteItem) 
++{
++    foreach (QWidget *widget, QApplication::topLevelWidgets()) {
++        PEMainWindow * peMainWindow = qobject_cast<PEMainWindow *>(widget);
++		if (peMainWindow == NULL) continue;		    
++		    
++        if (peMainWindow->editsModuleID(paletteItem->moduleID())) {
++            if (peMainWindow->isMinimized()) peMainWindow->showNormal();
++            else peMainWindow->show();
++	        peMainWindow->raise();
++            return;
++        }
++    }
++
++    PEMainWindow * peMainWindow = new PEMainWindow(m_referenceModel, NULL);
++    peMainWindow->init(m_referenceModel, NULL);
++   if (peMainWindow->setInitialItem(paletteItem)) {   
++	    peMainWindow->show();
++	    peMainWindow->raise();
++        connect(peMainWindow, SIGNAL(addToMyPartsSignal(ModelPart *)), this, SLOT(addToMyParts(ModelPart *)));
++   }
++   else {
++       delete peMainWindow;
++   }
++}
++
++void MainWindow::getPartsEditorNewAnd(ItemBase * fromItem) 
++{
++    PaletteItem * paletteItem = qobject_cast<PaletteItem *>(fromItem);
++    if (paletteItem == NULL) return;
++
++    openNewPartsEditor(paletteItem);
++}
++
++void MainWindow::openInPartsEditorNew() {
++	if (m_currentGraphicsView == NULL) return;
++
++	PaletteItem *selectedPart = m_currentGraphicsView->getSelectedPart();
++	openNewPartsEditor(selectedPart);
++}
++
++void MainWindow::createNewSketch() {
++    MainWindow* mw = newMainWindow(m_referenceModel, "", true, true);
++    mw->move(x()+CascadeFactorX,y()+CascadeFactorY);
++	ProcessEventBlocker::processEvents();
++
++	mw->addDefaultParts();
++    mw->show();
++	mw->hideTempPartsBin();
++
++    QSettings settings;
++    settings.remove("lastOpenSketch");
++    mw->clearFileProgressDialog();
++}
++
++void MainWindow::minimize() {
++	this->showMinimized();
++}
++
++void MainWindow::toggleToolbar(bool toggle) {
++	Q_UNUSED(toggle);
++	/*if(toggle) {
++		this->m_fileToolBar->show();
++		this->m_editToolBar->show();
++	} else {
++		this->m_fileToolBar->hide();
++		this->m_editToolBar->hide();
++	}*/
++}
++
++void MainWindow::togglePartLibrary(bool toggle) {
++	if(toggle) {
++		m_binManager->show();
++	} else {
++		m_binManager->hide();
++	}
++}
++
++void MainWindow::toggleInfo(bool toggle) {
++	if(toggle) {
++		((QDockWidget*)m_infoView->parent())->show();
++	} else {
++		((QDockWidget*)m_infoView->parent())->hide();
++	}
++}
++
++void MainWindow::toggleNavigator(bool toggle) {
++	if(toggle) {
++		((QDockWidget*)m_miniViewContainerBreadboard->parent())->show();
++		((QDockWidget*)m_miniViewContainerSchematic->parent())->show();
++		((QDockWidget*)m_miniViewContainerPCB->parent())->show();
++	} else {
++		((QDockWidget*)m_miniViewContainerBreadboard->parent())->hide();
++		((QDockWidget*)m_miniViewContainerSchematic->parent())->hide();
++		((QDockWidget*)m_miniViewContainerPCB->parent())->hide();
++	}
++}
++
++void MainWindow::toggleUndoHistory(bool toggle) {
++	if(toggle) {
++		((QDockWidget*)m_undoView->parent())->show();
++	} else {
++		((QDockWidget*)m_undoView->parent())->hide();
++	}
++}
++
++void MainWindow::toggleDebuggerOutput(bool toggle) {
++	if (toggle) {
++		DebugDialog::showDebug();
++	} 
++	else 
++	{
++	}
++}
++
++void MainWindow::updateWindowMenu() {
++	m_toggleDebuggerOutputAct->setChecked(DebugDialog::visible());
++	foreach (QWidget * widget, QApplication::topLevelWidgets()) {
++		MainWindow * mainWindow = qobject_cast<MainWindow *>(widget);
++		if (mainWindow == NULL) continue;
++
++		QAction *action = mainWindow->raiseWindowAction();
++        if (action != NULL) {
++		    action->setChecked(action == m_raiseWindowAct);
++		    m_windowMenu->addAction(action);
++        }
++	}
++}
++
++void MainWindow::pageSetup() {
++	notYetImplemented(tr("Page Setup"));
++}
++
++void MainWindow::notYetImplemented(QString action) {
++	QMessageBox::warning(this, tr("Fritzing"),
++				tr("Sorry, \"%1\" has not been implemented yet").arg(action));
++}
++
++void MainWindow::rotateIncCW() {
++	if (m_currentGraphicsView == NULL) return;
++
++	if (m_rotate45cwAct->isEnabled()) {
++		rotate45cw();
++	}
++	else if (m_rotate90cwAct->isEnabled()) {
++		rotate90cw();
++	}
++}
++
++void MainWindow::rotateIncCWRubberBand() {
++	if (m_currentGraphicsView == NULL) return;
++
++	if (m_rotate45cwAct->isEnabled()) {
++		m_currentGraphicsView->rotateX(45, true, NULL);
++	}
++	else if (m_rotate90cwAct->isEnabled()) {
++		m_currentGraphicsView->rotateX(90, true, NULL);
++	}
++}
++
++void MainWindow::rotateIncCCW() {
++	if (m_currentGraphicsView == NULL) return;
++
++	if (m_rotate45ccwAct->isEnabled()) {
++		m_currentGraphicsView->rotateX(315, true, NULL);
++	}
++	else if (m_rotate90ccwAct->isEnabled()) {
++		m_currentGraphicsView->rotateX(270, true, NULL);
++	}
++}
++
++void MainWindow::rotateIncCCWRubberBand() {
++	if (m_currentGraphicsView == NULL) return;
++
++	if (m_rotate45ccwAct->isEnabled()) {
++		m_currentGraphicsView->rotateX(315, true, NULL);
++	}
++	else if (m_rotate90ccwAct->isEnabled()) {
++		m_currentGraphicsView->rotateX(270, true, NULL);
++	}
++}
++
++void MainWindow::rotate90cw() {
++	if (m_currentGraphicsView == NULL) return;
++
++	m_currentGraphicsView->rotateX(90, false, NULL);
++}
++
++void MainWindow::rotate90ccw() {
++	if (m_currentGraphicsView == NULL) return;
++
++	m_currentGraphicsView->rotateX(270, false, NULL);
++}
++
++void MainWindow::rotate45ccw() {
++	if (m_currentGraphicsView == NULL) return;
++
++	m_currentGraphicsView->rotateX(315, false, NULL);
++}
++
++void MainWindow::rotate45cw() {
++	if (m_currentGraphicsView == NULL) return;
++
++	m_currentGraphicsView->rotateX(45, false, NULL);
++}
++
++void MainWindow::rotate180() {
++	if (m_currentGraphicsView == NULL) return;
++
++	m_currentGraphicsView->rotateX(180, false, NULL);
++}
++
++void MainWindow::flipHorizontal() {
++	m_currentGraphicsView->flipX(Qt::Horizontal, false);
++}
++
++void MainWindow::flipVertical() {
++	m_currentGraphicsView->flipX(Qt::Vertical, false);
++}
++
++void MainWindow::sendToBack() {
++	if (m_currentGraphicsView == NULL) return;
++
++	m_currentGraphicsView->sendToBack();
++}
++
++void MainWindow::sendBackward() {
++	if (m_currentGraphicsView == NULL) return;
++
++	m_currentGraphicsView->sendBackward();
++}
++
++void MainWindow::bringForward() {
++	if (m_currentGraphicsView == NULL) return;
++
++	m_currentGraphicsView->bringForward();
++}
++
++void MainWindow::bringToFront() {
++	if (m_currentGraphicsView == NULL) return;
++
++	m_currentGraphicsView->bringToFront();
++}
++
++void MainWindow::alignLeft() {
++	if (m_currentGraphicsView == NULL) return;
++
++	m_currentGraphicsView->alignItems(Qt::AlignLeft);
++}
++
++void MainWindow::alignVerticalCenter() {
++	if (m_currentGraphicsView == NULL) return;
++
++	m_currentGraphicsView->alignItems(Qt::AlignVCenter);
++}
++
++void MainWindow::alignRight() {
++	if (m_currentGraphicsView == NULL) return;
++
++	m_currentGraphicsView->alignItems(Qt::AlignRight);
++}
++
++void MainWindow::alignTop() {
++	if (m_currentGraphicsView == NULL) return;
++
++	m_currentGraphicsView->alignItems(Qt::AlignTop);
++}
++
++void MainWindow::alignHorizontalCenter() {
++	if (m_currentGraphicsView == NULL) return;
++
++	m_currentGraphicsView->alignItems(Qt::AlignHCenter);
++}
++
++void MainWindow::alignBottom() {
++	if (m_currentGraphicsView == NULL) return;
++
++	m_currentGraphicsView->alignItems(Qt::AlignBottom);
++}
++
++void MainWindow::showAllLayers() {
++	if (m_currentGraphicsView == NULL) return;
++
++	m_currentGraphicsView->setAllLayersVisible(true);
++	updateLayerMenu();
++}
++
++void MainWindow::hideAllLayers() {
++	if (m_currentGraphicsView == NULL) return;
++
++	m_currentGraphicsView->setAllLayersVisible(false);
++	updateLayerMenu();
++}
++
++void MainWindow::openURL() {
++	QAction *action = qobject_cast<QAction *>(sender());
++	if (action == NULL) return;
++
++	QString href = action->data().toString();
++	if (href.isEmpty()) return;
++
++	QDesktopServices::openUrl(href);
++}
++
++void MainWindow::openRecentOrExampleFile() {
++	QAction *action = qobject_cast<QAction *>(sender());
++	if (action) {
++		QString filename = action->data().toString();
++		if (alreadyOpen(filename)) {
++			return;
++		}
++
++		if (!QFileInfo(filename).exists()) {
++			QMessageBox::warning(NULL, tr("Fritzing"), tr("File '%1' not found").arg(filename));
++			return;
++		}
++
++		MainWindow* mw = newMainWindow(m_referenceModel, action->data().toString(), true, true);
++		bool readOnly = m_openExampleActions.contains(action->text());
++		mw->setReadOnly(readOnly);
++		mw->loadWhich(filename,!readOnly,!readOnly,"");
++		mw->clearFileProgressDialog();
++		closeIfEmptySketch(mw);
++	}
++}
++
++void MainWindow::removeActionsStartingAt(QMenu * menu, int start) {
++	QList<QAction*> actions = menu->actions();
++
++	if(start == 0) {
++		menu->clear();
++	} else {
++		for(int i=start; i < actions.size(); i++) {
++			menu->removeAction(actions.at(i));
++		}
++	}
++}
++
++void MainWindow::hideShowProgramMenu() {
++    bool show = (m_currentGraphicsView != NULL);
++    if (m_viewMenu) m_viewMenu->menuAction()->setVisible(show);
++    if (m_partMenu) m_partMenu->menuAction()->setVisible(show);
++    if (m_fileMenu) m_fileMenu->menuAction()->setVisible(show);
++    if (m_editMenu) m_editMenu->menuAction()->setVisible(show);
++    if (m_programView) m_programView->showMenus(!show);
++}
++
++void MainWindow::hideShowTraceMenu() {
++    if (m_pcbTraceMenu) m_pcbTraceMenu->menuAction()->setVisible(m_currentGraphicsView == m_pcbGraphicsView);
++	if (m_schematicTraceMenu) m_schematicTraceMenu->menuAction()->setVisible(m_currentGraphicsView == m_schematicGraphicsView);
++	if (m_breadboardTraceMenu) m_breadboardTraceMenu->menuAction()->setVisible(m_currentGraphicsView == m_breadboardGraphicsView);
++}
++
++void MainWindow::createTraceMenuActions() {
++	m_newAutorouteAct = new QAction(tr("Autoroute"), this);
++	m_newAutorouteAct->setStatusTip(tr("Autoroute connections..."));
++	m_newAutorouteAct->setShortcut(tr("Shift+Ctrl+A"));
++	connect(m_newAutorouteAct, SIGNAL(triggered()), this, SLOT(newAutoroute()));
++
++	createOrderFabAct();
++	createActiveLayerActions();
++
++	QAction * traceAct = new QAction(tr("&Create trace from ratsnest"), this);
++	traceAct->setStatusTip(tr("Create a trace from the ratsnest line"));
++	m_createTraceWireAct = new WireAction(traceAct);
++	connect(m_createTraceWireAct, SIGNAL(triggered()), this, SLOT(createTrace()));
++	traceAct = new QAction(tr("&Create wire from ratsnest"), this);
++	traceAct->setStatusTip(tr("Create a wire from the ratsnest line"));
++	m_createWireWireAct = new WireAction(traceAct);
++	connect(m_createWireWireAct, SIGNAL(triggered()), this, SLOT(createTrace()));
++
++	m_excludeFromAutorouteAct = new QAction(tr("Do not autoroute"), this);
++	m_excludeFromAutorouteAct->setStatusTip(tr("When autorouting, do not rip up this trace wire, via, or jumper item"));
++	connect(m_excludeFromAutorouteAct, SIGNAL(triggered()), this, SLOT(excludeFromAutoroute()));
++	m_excludeFromAutorouteAct->setCheckable(true);
++	m_excludeFromAutorouteWireAct = new WireAction(m_excludeFromAutorouteAct);
++	connect(m_excludeFromAutorouteWireAct, SIGNAL(triggered()), this, SLOT(excludeFromAutoroute()));
++
++    m_changeTraceLayerAct = new QAction(tr("Move to other side of the board"), this);
++	m_changeTraceLayerAct->setStatusTip(tr("Move selected traces to the other side of the board (note: the 'first' trace will be moved and the rest will follow to the same side)"));
++	connect(m_changeTraceLayerAct, SIGNAL(triggered()), this, SLOT(changeTraceLayer()));
++	m_changeTraceLayerWireAct = new WireAction(m_changeTraceLayerAct);
++	connect(m_changeTraceLayerWireAct, SIGNAL(triggered()), this, SLOT(changeTraceLayer()));
++
++    m_showUnroutedAct = new QAction(tr("Show unrouted"), this);
++	m_showUnroutedAct->setStatusTip(tr("Highlight all unrouted connectors"));
++	connect(m_showUnroutedAct, SIGNAL(triggered()), this, SLOT(showUnrouted()));
++
++	m_selectAllTracesAct = new QAction(tr("Select All Traces"), this);
++	m_selectAllTracesAct->setStatusTip(tr("Select all trace wires"));
++	connect(m_selectAllTracesAct, SIGNAL(triggered()), this, SLOT(selectAllTraces()));
++
++	m_selectAllWiresAct = new QAction(tr("Select All Wires"), this);
++	m_selectAllWiresAct->setStatusTip(tr("Select all wires"));
++	connect(m_selectAllWiresAct, SIGNAL(triggered()), this, SLOT(selectAllTraces()));
++
++	m_selectAllCopperFillAct = new QAction(tr("Select All CopperFill"), this);
++	m_selectAllCopperFillAct->setStatusTip(tr("Select all copper fill items"));
++	connect(m_selectAllCopperFillAct, SIGNAL(triggered()), this, SLOT(selectAllCopperFill()));
++
++	m_updateRoutingStatusAct = new QAction(tr("Force Update Routing Status and Ratsnests"), this);
++	m_updateRoutingStatusAct->setStatusTip(tr("Recalculate routing status and ratsnest wires (in case the auto-update isn't working correctly)"));
++	connect(m_updateRoutingStatusAct, SIGNAL(triggered()), this, SLOT(updateRoutingStatus()));
++
++	m_selectAllExcludedTracesAct = new QAction(tr("Select All \"Don't Autoroute\" Traces"), this);
++	m_selectAllExcludedTracesAct->setStatusTip(tr("Select all trace wires excluded from autorouting"));
++	connect(m_selectAllExcludedTracesAct, SIGNAL(triggered()), this, SLOT(selectAllExcludedTraces()));
++
++	m_selectAllIncludedTracesAct = new QAction(tr("Select All Autoroutable Traces"), this);
++	m_selectAllIncludedTracesAct->setStatusTip(tr("Select all trace wires that can be changed during autorouting"));
++	connect(m_selectAllIncludedTracesAct, SIGNAL(triggered()), this, SLOT(selectAllIncludedTraces()));
++
++	m_selectAllJumperItemsAct = new QAction(tr("Select All Jumpers"), this);
++	m_selectAllJumperItemsAct->setStatusTip(tr("Select all jumper item parts"));
++	connect(m_selectAllJumperItemsAct, SIGNAL(triggered()), this, SLOT(selectAllJumperItems()));
++
++	m_selectAllViasAct = new QAction(tr("Select All Vias"), this);
++	m_selectAllViasAct->setStatusTip(tr("Select all via parts"));
++	connect(m_selectAllViasAct, SIGNAL(triggered()), this, SLOT(selectAllVias()));
++
++	m_tidyWiresAct = new QAction(tr("Tidy Wires"), this);
++	m_tidyWiresAct->setStatusTip(tr("Tidy selected wires"));
++	connect(m_tidyWiresAct, SIGNAL(triggered()), this, SLOT(tidyWires()));
++
++	m_groundFillAct = new QAction(tr("Ground Fill"), this);
++	m_groundFillAct->setStatusTip(tr("Fill empty regions of the copper layer--fill will include all traces connected to a GROUND"));
++	connect(m_groundFillAct, SIGNAL(triggered()), this, SLOT(groundFill()));
++
++	m_copperFillAct = new QAction(tr("Copper Fill"), this);
++	m_copperFillAct->setStatusTip(tr("Fill empty regions of the copper layer--not including traces connected to a GROUND"));
++	connect(m_copperFillAct, SIGNAL(triggered()), this, SLOT(copperFill()));
++
++	m_removeGroundFillAct = new QAction(tr("Remove Copper Fill"), this);
++	m_removeGroundFillAct->setStatusTip(tr("Remove the copper fill"));
++	connect(m_removeGroundFillAct, SIGNAL(triggered()), this, SLOT(removeGroundFill()));
++
++	m_setGroundFillSeedsAct = new QAction(tr("Choose Ground Fill Seed(s)..."), this);
++	m_setGroundFillSeedsAct->setStatusTip(tr("Fill empty regions of the copper layer--fill will include all traces connected to the seeds"));
++	connect(m_setGroundFillSeedsAct, SIGNAL(triggered()), this, SLOT(setGroundFillSeeds()));
++
++	m_setOneGroundFillSeedAct = new ConnectorItemAction(tr("Set Ground Fill Seed"), this);
++	m_setOneGroundFillSeedAct->setStatusTip(tr("Treat this connector and its connections as a 'ground' during ground fill."));
++	m_setOneGroundFillSeedAct->setCheckable(true);
++	connect(m_setOneGroundFillSeedAct, SIGNAL(triggered()), this, SLOT(setOneGroundFillSeed()));
++
++	m_clearGroundFillSeedsAct = new ConnectorItemAction(tr("Clear Ground Fill Seeds"), this);
++	m_clearGroundFillSeedsAct->setStatusTip(tr("Clear ground fill seeds--enable copper fill only."));
++	connect(m_clearGroundFillSeedsAct, SIGNAL(triggered()), this, SLOT(clearGroundFillSeeds()));
++
++	m_setGroundFillKeepoutAct = new QAction(tr("Set Ground Fill Keepout..."), this);
++	m_setGroundFillKeepoutAct->setStatusTip(tr("Set the minimum distance between ground fill and traces or connectors"));
++	connect(m_setGroundFillKeepoutAct, SIGNAL(triggered()), this, SLOT(setGroundFillKeepout()));
++
++
++
++	m_newDesignRulesCheckAct = new QAction(tr("Design Rules Check (DRC)"), this);
++	m_newDesignRulesCheckAct->setStatusTip(tr("Highlights any parts that are too close together for safe board production"));
++	m_newDesignRulesCheckAct->setShortcut(tr("Shift+Ctrl+D"));
++	connect(m_newDesignRulesCheckAct, SIGNAL(triggered()), this, SLOT(newDesignRulesCheck()));
++
++	m_checkLoadedTracesAct = new QAction(tr("Check Loaded Traces"), this);
++	m_checkLoadedTracesAct->setStatusTip(tr("Select any traces where the screen location doesn't match the actual location. Only needed for sketches autorouted with version 0.7.10 or earlier"));
++	connect(m_checkLoadedTracesAct, SIGNAL(triggered()), this, SLOT(checkLoadedTraces()));
++
++	m_autorouterSettingsAct = new QAction(tr("Autorouter/DRC settings..."), this);
++	m_autorouterSettingsAct->setStatusTip(tr("Set autorouting parameters including keepout..."));
++	connect(m_autorouterSettingsAct, SIGNAL(triggered()), this, SLOT(autorouterSettings()));
++
++	m_fabQuoteAct = new QAction(tr("Fritzing Fab Quote..."), this);
++	m_fabQuoteAct->setStatusTip(tr("How much would it could to produce a PCB from this sketch with Fritzing Fab"));
++	connect(m_fabQuoteAct, SIGNAL(triggered()), this, SLOT(fabQuote()));
++
++}
++
++void MainWindow::createActiveLayerActions() {
++
++	m_viewFromBelowToggleAct = new QAction(tr("View from below"), this);
++	m_viewFromBelowToggleAct->setStatusTip(tr("View the PCB from the bottom layers upwards"));
++    m_viewFromBelowToggleAct->setCheckable(true);
++    m_viewFromBelowToggleAct->setChecked(false);
++	connect(m_viewFromBelowToggleAct, SIGNAL(triggered()), this, SLOT(setViewFromBelowToggle()));
++
++	m_viewFromBelowAct = new QAction(tr("View from below"), this);
++	m_viewFromBelowAct->setStatusTip(tr("View the PCB from the bottom layers upwards"));
++	connect(m_viewFromBelowAct, SIGNAL(triggered()), this, SLOT(setViewFromBelow()));
++
++	m_viewFromAboveAct = new QAction(tr("View from above"), this);
++	m_viewFromAboveAct->setStatusTip(tr("View the PCB from the top layers downwards"));
++	connect(m_viewFromAboveAct, SIGNAL(triggered()), this, SLOT(setViewFromAbove()));
++
++	m_activeLayerBothAct = new QAction(tr("Set both copper layers clickable"), this);
++	m_activeLayerBothAct->setStatusTip(tr("Set both copper layers clickable"));
++	m_activeLayerBothAct->setShortcut(tr("Shift+Ctrl+3"));
++	connect(m_activeLayerBothAct, SIGNAL(triggered()), this, SLOT(activeLayerBoth()));
++
++	m_activeLayerTopAct = new QAction(tr("Set copper top layer clickable"), this);
++	m_activeLayerTopAct->setStatusTip(tr("Set copper top layer clickable"));
++	m_activeLayerTopAct->setShortcut(tr("Shift+Ctrl+2"));
++	connect(m_activeLayerTopAct, SIGNAL(triggered()), this, SLOT(activeLayerTop()));
++
++	m_activeLayerBottomAct = new QAction(tr("Set copper bottom layer clickable"), this);
++	m_activeLayerBottomAct->setStatusTip(tr("Set copper bottom layer clickable"));
++	m_activeLayerBottomAct->setShortcut(tr("Shift+Ctrl+1"));
++	connect(m_activeLayerBottomAct, SIGNAL(triggered()), this, SLOT(activeLayerBottom()));
++}
++
++void MainWindow::activeLayerBoth() {
++	PCBSketchWidget * pcbSketchWidget = qobject_cast<PCBSketchWidget *>(m_currentGraphicsView);
++	if (pcbSketchWidget == NULL) return;
++
++	pcbSketchWidget->setLayerActive(ViewLayer::Copper1, true);
++	pcbSketchWidget->setLayerActive(ViewLayer::Copper0, true);
++	pcbSketchWidget->setLayerActive(ViewLayer::Silkscreen0, true);
++	pcbSketchWidget->setLayerActive(ViewLayer::Silkscreen1, true);
++	AutoCloseMessageBox::showMessage(this, tr("Copper Top and Copper Bottom layers are both active"));
++	updateActiveLayerButtons();
++}
++
++void MainWindow::activeLayerTop() {
++	PCBSketchWidget * pcbSketchWidget = qobject_cast<PCBSketchWidget *>(m_currentGraphicsView);
++	if (pcbSketchWidget == NULL) return;
++
++	pcbSketchWidget->setLayerActive(ViewLayer::Copper1, true);
++	pcbSketchWidget->setLayerActive(ViewLayer::Silkscreen1, true);
++	pcbSketchWidget->setLayerActive(ViewLayer::Copper0, false);
++	pcbSketchWidget->setLayerActive(ViewLayer::Silkscreen0, false);
++	AutoCloseMessageBox::showMessage(this, tr("Copper Top layer is active"));
++	updateActiveLayerButtons();
++}
++
++void MainWindow::activeLayerBottom() {
++	PCBSketchWidget * pcbSketchWidget = qobject_cast<PCBSketchWidget *>(m_currentGraphicsView);
++	if (pcbSketchWidget == NULL) return;
++
++	pcbSketchWidget->setLayerActive(ViewLayer::Copper1, false);
++	pcbSketchWidget->setLayerActive(ViewLayer::Silkscreen1, false);
++	pcbSketchWidget->setLayerActive(ViewLayer::Copper0, true);
++	pcbSketchWidget->setLayerActive(ViewLayer::Silkscreen0, true);
++	AutoCloseMessageBox::showMessage(this, tr("Copper Bottom layer is active"));
++	updateActiveLayerButtons();
++}
++
++void MainWindow::toggleActiveLayer() 
++{
++	PCBSketchWidget * pcbSketchWidget = qobject_cast<PCBSketchWidget *>(m_currentGraphicsView);
++	if (pcbSketchWidget == NULL) return;
++
++	int index = activeLayerIndex();
++	switch (index) {
++		case 0:
++			activeLayerBottom();
++			return;
++		case 1:
++			activeLayerTop();
++			return;
++		case 2:
++			activeLayerBoth();
++			return;
++		default:
++			return;
++	}
++}
++
++
++void MainWindow::createOrderFabAct() {
++	if (m_orderFabAct != NULL) return;
++
++	m_orderFabAct = new QAction(tr("Order a PCB..."), this);
++	m_orderFabAct->setStatusTip(tr("Order a PCB created from your sketch--from fabulous Fritzing Fab"));
++	connect(m_orderFabAct, SIGNAL(triggered()), this, SLOT(orderFab()));
++}
++
++
++void MainWindow::newAutoroute() {
++	PCBSketchWidget * pcbSketchWidget = qobject_cast<PCBSketchWidget *>(m_currentGraphicsView);
++	if (pcbSketchWidget == NULL) return;
++
++    ItemBase * board = NULL;
++    if (pcbSketchWidget->autorouteTypePCB()) {
++        int boardCount;
++		board = pcbSketchWidget->findSelectedBoard(boardCount);
++        if (boardCount == 0) {
++            QMessageBox::critical(this, tr("Fritzing"),
++                       tr("Your sketch does not have a board yet!  Please add a PCB in order to use the autorouter."));
++            return;
++        }
++        if (board == NULL) {
++            QMessageBox::critical(this, tr("Fritzing"),
++                       tr("Please select the board you want to autoroute. The autorouter can only handle one board at a time."));
++            return;
++        }
++	}
++   
++    dynamic_cast<SketchAreaWidget *>(pcbSketchWidget->parent())->routingStatusLabel()->setText(tr("Autorouting..."));
++
++	bool copper0Active = pcbSketchWidget->layerIsActive(ViewLayer::Copper0);
++	bool copper1Active = pcbSketchWidget->layerIsActive(ViewLayer::Copper1);
++
++	AutorouteProgressDialog progress(tr("Autorouting Progress..."), true, true, true, true, pcbSketchWidget, this);
++	progress.setModal(true);
++	progress.show();
++	QRect pr = progress.frameGeometry();
++	QRect wr = this->frameGeometry();
++	progress.move(wr.right() - pr.width(), pr.top());
++
++
++	pcbSketchWidget->scene()->clearSelection();
++	pcbSketchWidget->setIgnoreSelectionChangeEvents(true);
++	Autorouter * autorouter = NULL;
++    autorouter = new MazeRouter(pcbSketchWidget, board, true);
++
++	connect(autorouter, SIGNAL(wantTopVisible()), this, SLOT(activeLayerTop()), Qt::DirectConnection);
++	connect(autorouter, SIGNAL(wantBottomVisible()), this, SLOT(activeLayerBottom()), Qt::DirectConnection);
++	connect(autorouter, SIGNAL(wantBothVisible()), this, SLOT(activeLayerBoth()), Qt::DirectConnection);
++
++	connect(&progress, SIGNAL(cancel()), autorouter, SLOT(cancel()), Qt::DirectConnection);
++	connect(&progress, SIGNAL(skip()), autorouter, SLOT(cancelTrace()), Qt::DirectConnection);
++	connect(&progress, SIGNAL(stop()), autorouter, SLOT(stopTracing()), Qt::DirectConnection);
++	connect(&progress, SIGNAL(best()), autorouter, SLOT(useBest()), Qt::DirectConnection);
++	connect(&progress, SIGNAL(spinChange(int)), autorouter, SLOT(setMaxCycles(int)), Qt::DirectConnection);
++
++	connect(autorouter, SIGNAL(setMaximumProgress(int)), &progress, SLOT(setMaximum(int)), Qt::DirectConnection);
++	connect(autorouter, SIGNAL(setProgressValue(int)), &progress, SLOT(setValue(int)), Qt::DirectConnection);
++	connect(autorouter, SIGNAL(setProgressMessage(const QString &)), &progress, SLOT(setMessage(const QString &)));
++	connect(autorouter, SIGNAL(setProgressMessage2(const QString &)), &progress, SLOT(setMessage2(const QString &)));
++	connect(autorouter, SIGNAL(setCycleMessage(const QString &)), &progress, SLOT(setSpinLabel(const QString &)));
++	connect(autorouter, SIGNAL(setCycleCount(int)), &progress, SLOT(setSpinValue(int)));
++	connect(autorouter, SIGNAL(disableButtons()), &progress, SLOT(disableButtons()));
++
++	ProcessEventBlocker::processEvents();
++	ProcessEventBlocker::block();
++
++	autorouter->start();
++	pcbSketchWidget->setIgnoreSelectionChangeEvents(false);
++
++	delete autorouter;
++
++	pcbSketchWidget->setLayerActive(ViewLayer::Copper1, copper1Active);
++	pcbSketchWidget->setLayerActive(ViewLayer::Silkscreen1, copper1Active);
++	pcbSketchWidget->setLayerActive(ViewLayer::Copper0, copper0Active);
++	pcbSketchWidget->setLayerActive(ViewLayer::Silkscreen0, copper0Active);
++	updateActiveLayerButtons();
++
++	ProcessEventBlocker::unblock();
++}
++
++void MainWindow::createTrace() {
++	m_currentGraphicsView->createTrace(retrieveWire(), true);
++}
++
++void MainWindow::excludeFromAutoroute() {
++	Wire * wire = retrieveWire();
++	PCBSketchWidget * pcbSketchWidget = qobject_cast<PCBSketchWidget *>(m_currentGraphicsView);
++	if (pcbSketchWidget == NULL) return;
++
++	pcbSketchWidget->excludeFromAutoroute(wire == NULL ? m_excludeFromAutorouteAct->isChecked() : m_excludeFromAutorouteWireAct->isChecked());
++}
++
++void MainWindow::selectAllTraces() 
++{
++	m_currentGraphicsView->selectAllWires(m_currentGraphicsView->getTraceFlag());
++}
++
++void MainWindow::updateRoutingStatus() {
++	RoutingStatus routingStatus;
++	routingStatus.zero();
++	m_currentGraphicsView->updateRoutingStatus(NULL, routingStatus, true);
++}
++
++void MainWindow::selectAllExcludedTraces() {
++	PCBSketchWidget * pcbSketchWidget = qobject_cast<PCBSketchWidget *>(m_currentGraphicsView);
++	if (pcbSketchWidget == NULL) return;
++
++    pcbSketchWidget->selectAllExcludedTraces();
++}
++
++void MainWindow::selectAllIncludedTraces() {
++	PCBSketchWidget * pcbSketchWidget = qobject_cast<PCBSketchWidget *>(m_currentGraphicsView);
++	if (pcbSketchWidget == NULL) return;
++
++    pcbSketchWidget->selectAllIncludedTraces();
++}
++
++void MainWindow::selectAllJumperItems() {
++	m_pcbGraphicsView->selectAllItemType(ModelPart::Jumper, tr("jumpers"));
++}
++
++void MainWindow::selectAllCopperFill() {
++	m_pcbGraphicsView->selectAllItemType(ModelPart::CopperFill, tr("copperfill"));
++}
++
++void MainWindow::selectAllVias() {
++	m_pcbGraphicsView->selectAllItemType(ModelPart::Via, tr("vias"));
++}
++
++void MainWindow::notClosableForAWhile() {
++	m_dontClose = true;
++
++	QTimer::singleShot(500, this, SLOT(ensureClosable()));
++}
++
++void MainWindow::ensureClosable() {
++	m_dontClose = false;
++}
++
++void MainWindow::showPartLabels() {
++	if (m_currentGraphicsView == NULL) return;
++
++	m_currentGraphicsView->showPartLabels(m_showPartLabelAct->data().toBool());
++}
++
++void MainWindow::addNote() {
++	if (m_currentGraphicsView == NULL) return;
++
++	ViewGeometry vg;
++	vg.setRect(0, 0, Note::initialMinWidth, Note::initialMinHeight);
++	QPointF tl = m_currentGraphicsView->mapToScene(QPoint(0, 0));
++	QSizeF vpSize = m_currentGraphicsView->viewport()->size();
++	tl.setX(tl.x() + ((vpSize.width() - Note::initialMinWidth) / 2.0));
++	tl.setY(tl.y() + ((vpSize.height() - Note::initialMinHeight) / 2.0));
++	vg.setLoc(tl);
++
++	QUndoCommand * parentCommand = new QUndoCommand(tr("Add Note"));
++	m_currentGraphicsView->stackSelectionState(false, parentCommand);
++	m_currentGraphicsView->scene()->clearSelection();
++	new AddItemCommand(m_currentGraphicsView, BaseCommand::SingleView, ModuleIDNames::NoteModuleIDName, m_currentGraphicsView->defaultViewLayerPlacement(NULL), vg, ItemBase::getNextID(), false, -1, parentCommand);
++	m_undoStack->push(parentCommand);
++}
++
++bool MainWindow::alreadyOpen(const QString & fileName) {
++    foreach (QWidget * widget, QApplication::topLevelWidgets()) {
++        MainWindow * mainWindow = qobject_cast<MainWindow *>(widget);
++        if (mainWindow == NULL) continue;
++
++		// don't load two copies of the same file
++		if (mainWindow->fileName().compare(fileName) == 0) {
++			mainWindow->raise();
++			return true;
++		}
++    }
++
++	return false;
++}
++
++void MainWindow::enableAddBendpointAct(QGraphicsItem * graphicsItem) {
++	m_addBendpointAct->setEnabled(false);
++	m_convertToViaAct->setEnabled(false);
++	m_flattenCurveAct->setEnabled(false);
++
++	Wire * wire = dynamic_cast<Wire *>(graphicsItem);
++	if (wire == NULL) return;
++	if (wire->getRatsnest()) return;
++
++	m_flattenCurveAct->setEnabled(wire->isCurved());
++
++	BendpointAction * bendpointAction = qobject_cast<BendpointAction *>(m_addBendpointAct);
++	BendpointAction * convertToViaAction = qobject_cast<BendpointAction *>(m_convertToViaAct);
++	FGraphicsScene * scene = qobject_cast<FGraphicsScene *>(graphicsItem->scene());
++	if (scene != NULL) {
++		bendpointAction->setLastLocation(scene->lastContextMenuPos());
++		convertToViaAction->setLastLocation(scene->lastContextMenuPos());
++	}
++
++	bool enabled = false;
++    bool ctvEnabled = false;
++	if (m_currentGraphicsView->lastHoverEnterConnectorItem()) {
++		bendpointAction->setText(tr("Remove Bendpoint"));
++		bendpointAction->setLastHoverEnterConnectorItem(m_currentGraphicsView->lastHoverEnterConnectorItem());
++		bendpointAction->setLastHoverEnterItem(NULL);
++		convertToViaAction->setLastHoverEnterConnectorItem(m_currentGraphicsView->lastHoverEnterConnectorItem());
++		convertToViaAction->setLastHoverEnterItem(NULL);
++		ctvEnabled = enabled = true;
++	}
++	else if (m_currentGraphicsView->lastHoverEnterItem()) {
++		bendpointAction->setText(tr("Add Bendpoint"));
++		bendpointAction->setLastHoverEnterItem(m_currentGraphicsView->lastHoverEnterItem());
++		bendpointAction->setLastHoverEnterConnectorItem(NULL);
++		convertToViaAction->setLastHoverEnterItem(NULL);
++		convertToViaAction->setLastHoverEnterConnectorItem(NULL);
++		enabled = true;
++	}
++	else {
++		bendpointAction->setLastHoverEnterItem(NULL);
++		bendpointAction->setLastHoverEnterConnectorItem(NULL);
++		convertToViaAction->setLastHoverEnterItem(NULL);
++		convertToViaAction->setLastHoverEnterConnectorItem(NULL);
++	}
++
++	m_addBendpointAct->setEnabled(enabled);
++	m_convertToViaAct->setEnabled(ctvEnabled && (m_currentGraphicsView == m_pcbGraphicsView));
++}
++
++void MainWindow::addBendpoint()
++{
++	BendpointAction * bendpointAction = qobject_cast<BendpointAction *>(m_addBendpointAct);
++
++	m_currentGraphicsView->addBendpoint(bendpointAction->lastHoverEnterItem(),
++										bendpointAction->lastHoverEnterConnectorItem(),
++										bendpointAction->lastLocation());
++}
++
++void MainWindow::convertToVia()
++{
++	BendpointAction * bendpointAction = qobject_cast<BendpointAction *>(m_convertToViaAct);
++
++	m_pcbGraphicsView->convertToVia(bendpointAction->lastHoverEnterConnectorItem());
++}
++
++void MainWindow::convertToBendpoint()
++{
++    m_pcbGraphicsView->convertToBendpoint();
++}
++
++void MainWindow::flattenCurve()
++{
++	BendpointAction * bendpointAction = qobject_cast<BendpointAction *>(m_addBendpointAct);
++
++	m_currentGraphicsView->flattenCurve(bendpointAction->lastHoverEnterItem(),
++										bendpointAction->lastHoverEnterConnectorItem(),
++										bendpointAction->lastLocation());
++}
++
++
++void MainWindow::importFilesFromPrevInstall() {
++	QString prevInstallPath = QFileDialog::getExistingDirectory(
++			this,
++			tr("Please choose the previous Fritzing folder..."),
++            QDir::homePath(),
++            QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks);
++	if(prevInstallPath.isNull()) return;
++	if(!QFileInfo(prevInstallPath+"/parts").exists()) {
++		QMessageBox::critical(
++			this, QObject::tr("Fritzing"),
++			tr("The folder \"%1\" isn't a Fritzing installation folder").arg(prevInstallPath));
++		return;
++	}
++
++	QString userDataPath = FolderUtils::getUserDataStorePath();
++
++	// replicate dirs
++	QStringList foldersToCopy = FolderUtils::getUserDataStoreFolders();
++	foreach(QString folder, foldersToCopy) {
++        FolderUtils::replicateDir(QDir(prevInstallPath+folder), QDir(userDataPath+folder));
++	}
++
++	// cleanup old bins
++	QDir dataStoreBins(userDataPath);
++	dataStoreBins.cd("bins");
++	QStringList binsToRemove;
++	binsToRemove
++		<< "allParts.fzb" << "artreenoBin.fzb"
++		<< "E6SetBin.fzb" << "pin_headers.fzb";
++	foreach(QString binToRemove, binsToRemove) {
++		dataStoreBins.remove(binToRemove);
++	}
++
++	// make sure to add the old my_parts.fzp to the folder
++	QString myPartsBinRelPath = "/bins/my_parts.fzb";
++	QFile myOldPartsBinFile(prevInstallPath+myPartsBinRelPath);
++	if(myOldPartsBinFile.exists()) {
++		QDateTime now = QDateTime::currentDateTime();
++		QString newNamePostfix = QString("__imported_on__%1.fzb").arg(now.toString("yyyy-MM-dd_hh-mm-ss"));
++		myOldPartsBinFile.copy(userDataPath+myPartsBinRelPath.replace(".fzb",newNamePostfix));
++	}
++
++	QMessageBox::information(
++		this, QObject::tr("Fritzing"),
++		tr("You will have to restart Fritzing in order to use the imported parts"));
++}
++
++void MainWindow::tidyWires() {
++	m_currentGraphicsView->tidyWires();
++}
++
++void MainWindow::copperFill() {
++	groundFillAux2(false);
++}
++
++void MainWindow::groundFill()
++{
++    groundFillAux2(true);
++}
++
++void MainWindow::groundFillAux2(bool fillGroundTraces) {
++
++    if (m_pcbGraphicsView->layerIsActive(ViewLayer::Copper0) && m_pcbGraphicsView->layerIsActive(ViewLayer::Copper1)) {
++	    groundFillAux(fillGroundTraces, ViewLayer::UnknownLayer);
++    }
++    else if (m_pcbGraphicsView->layerIsActive(ViewLayer::Copper0)) {
++        groundFillAux(fillGroundTraces, ViewLayer::GroundPlane0);
++    }
++    else {
++        groundFillAux(fillGroundTraces, ViewLayer::GroundPlane1);
++    }
++}
++
++void MainWindow::copperFill(ViewLayer::ViewLayerID viewLayerID) {
++	groundFillAux(false, viewLayerID);
++}
++
++void MainWindow::groundFill(ViewLayer::ViewLayerID viewLayerID)
++{
++	groundFillAux(true, viewLayerID);
++}
++
++void MainWindow::groundFillAux(bool fillGroundTraces, ViewLayer::ViewLayerID viewLayerID)
++{
++	// TODO:
++	//		what about leftover temp files from crashes?
++	//		clear ground plane when anything changes
++	//		some polygons can be combined
++	//		remove old ground plane modules from paletteModel and database
++
++	if (m_pcbGraphicsView == NULL) return;
++
++    int boardCount;
++    ItemBase * board = m_pcbGraphicsView->findSelectedBoard(boardCount);
++    if (boardCount == 0) {
++        QMessageBox::critical(this, tr("Fritzing"),
++                   tr("Your sketch does not have a board yet!  Please add a PCB in order to use ground or copper fill."));
++        return;
++    }
++    if (board == NULL) {
++        QMessageBox::critical(this, tr("Fritzing"),
++                   tr("Please select a PCB--copper fill only works for one board at a time."));
++        return;
++    }
++
++
++    FileProgressDialog fileProgress(tr("Generating %1 fill...").arg(fillGroundTraces ? tr("ground") : tr("copper")), 0, this);
++    fileProgress.setIndeterminate();
++	QUndoCommand * parentCommand = new QUndoCommand(fillGroundTraces ? tr("Ground Fill") : tr("Copper Fill"));
++    m_pcbGraphicsView->blockUI(true);
++    removeGroundFill(viewLayerID, parentCommand);
++	if (m_pcbGraphicsView->groundFill(fillGroundTraces, viewLayerID, parentCommand)) {
++		m_undoStack->push(parentCommand);
++	}
++	else {
++		delete parentCommand;
++	}
++    m_pcbGraphicsView->blockUI(false);
++}
++
++void MainWindow::removeGroundFill() {
++    removeGroundFill(ViewLayer::UnknownLayer, NULL);
++}
++
++void MainWindow::removeGroundFill(ViewLayer::ViewLayerID viewLayerID, QUndoCommand * parentCommand) {
++	QSet<ItemBase *> toDelete;
++    int boardCount;
++    ItemBase * board = m_pcbGraphicsView->findSelectedBoard(boardCount);
++    if (boardCount == 0) {
++        QMessageBox::critical(this, tr("Fritzing"),
++                   tr("Your sketch does not have a board yet!  Please add a PCB in order to remove copper fill."));
++        return;
++    }
++    if (board == NULL) {
++        QMessageBox::critical(this, tr("Fritzing"),
++                   tr("Please select a PCB--ground fill operations only work on a one board at a time."));
++        return;
++    }
++
++	foreach (QGraphicsItem * item, m_pcbGraphicsView->scene()->collidingItems(board)) {
++		ItemBase * itemBase = dynamic_cast<ItemBase *>(item);
++		if (itemBase == NULL) continue;
++        if (itemBase->moveLock()) continue;
++        if (!isGroundFill(itemBase)) continue;
++
++        if (viewLayerID != ViewLayer::UnknownLayer) {
++            if (itemBase->viewLayerID() != viewLayerID) continue;
++        }
++
++		toDelete.insert(itemBase->layerKinChief());
++	}
++
++    if (toDelete.count() == 0) return;
++
++
++    bool push = (parentCommand == NULL);
++
++    if (push) {
++	    parentCommand = new QUndoCommand(tr("Remove copper fill"));
++    }
++
++	new CleanUpWiresCommand(m_pcbGraphicsView, CleanUpWiresCommand::UndoOnly, parentCommand);
++	new CleanUpRatsnestsCommand(m_pcbGraphicsView, CleanUpWiresCommand::UndoOnly, parentCommand);
++
++    m_pcbGraphicsView->deleteMiddle(toDelete, parentCommand);
++	foreach (ItemBase * itemBase, toDelete) {
++        itemBase->saveGeometry();
++		m_pcbGraphicsView->makeDeleteItemCommand(itemBase, BaseCommand::CrossView, parentCommand);
++	}
++
++	new CleanUpRatsnestsCommand(m_pcbGraphicsView, CleanUpWiresCommand::RedoOnly, parentCommand);
++	new CleanUpWiresCommand(m_pcbGraphicsView, CleanUpWiresCommand::RedoOnly, parentCommand);
++
++    if (push) {
++	    m_undoStack->push(parentCommand);
++    }
++    else {
++        foreach (ItemBase * itemBase, toDelete) {
++            // move them out of the way because they are about to be deleted anyhow
++            itemBase->setPos(itemBase->pos() + board->sceneBoundingRect().bottomRight() + QPointF(10000, 10000));
++        }
++    }
++}
++
++bool MainWindow::isGroundFill(ItemBase * itemBase) {
++	return (itemBase->itemType() == ModelPart::CopperFill);
++}
++
++
++QMenu *MainWindow::breadboardItemMenu() {
++	QMenu *menu = new QMenu(QObject::tr("Part"), this);
++	menu->addMenu(m_rotateMenu);
++	return viewItemMenuAux(menu);
++}
++
++QMenu *MainWindow::schematicItemMenu() {
++	QMenu *menu = new QMenu(QObject::tr("Part"), this);
++	menu->addMenu(m_rotateMenu);
++	menu->addAction(m_flipHorizontalAct);
++	menu->addAction(m_flipVerticalAct);
++	return viewItemMenuAux(menu);
++}
++
++QMenu *MainWindow::pcbItemMenu() {
++	QMenu *menu = new QMenu(QObject::tr("Part"), this);
++	menu->addMenu(m_rotateMenu);
++	menu = viewItemMenuAux(menu);
++    menu->addAction(m_hidePartSilkscreenAct);
++	menu->addSeparator();
++    menu->addAction(m_convertToBendpointAct);
++	m_convertToBendpointSeparator = menu->addSeparator();
++	menu->addAction(m_setOneGroundFillSeedAct);
++	menu->addAction(m_clearGroundFillSeedsAct);
++	return menu;
++}
++
++QMenu *MainWindow::breadboardWireMenu() {
++	QMenu *menu = new QMenu(QObject::tr("Wire"), this);
++	menu->addMenu(m_zOrderWireMenu);
++	menu->addSeparator();
++	m_breadboardWireColorMenu = menu->addMenu(tr("&Wire Color"));
++	foreach(QString colorName, Wire::colorNames) {
++		QString colorValue = Wire::colorTrans.value(colorName);
++		QAction * action = new QAction(colorName, this);
++		m_breadboardWireColorMenu->addAction(action);
++		action->setData(colorValue);
++		action->setCheckable(true);
++        action->setChecked(false);
++		connect(action, SIGNAL(triggered(bool)), this, SLOT(changeWireColor(bool)));
++	}
++	menu->addAction(m_createWireWireAct);
++	menu->addSeparator();
++	menu->addAction(m_deleteWireAct);
++	menu->addAction(m_deleteWireMinusAct);
++	menu->addSeparator();
++	menu->addAction(m_addBendpointAct);
++	menu->addAction(m_flattenCurveAct);
++
++#ifndef QT_NO_DEBUG
++	menu->addSeparator();
++	menu->addAction(m_infoViewOnHoverAction);
++#endif
++
++    connect( menu, SIGNAL(aboutToShow()), this, SLOT(updateWireMenu()));
++
++	return menu;
++}
++
++QMenu *MainWindow::pcbWireMenu() {
++	QMenu *menu = new QMenu(QObject::tr("Wire"), this);
++	menu->addMenu(m_zOrderWireMenu);
++	menu->addSeparator();
++	menu->addAction(m_changeTraceLayerWireAct);	
++	menu->addAction(m_createTraceWireAct);
++	menu->addAction(m_excludeFromAutorouteWireAct);
++	menu->addSeparator();
++	menu->addAction(m_deleteWireAct);
++	menu->addAction(m_deleteWireMinusAct);
++	menu->addSeparator();
++	menu->addAction(m_addBendpointAct);
++	menu->addAction(m_convertToViaAct);
++	menu->addAction(m_flattenCurveAct);
++
++#ifndef QT_NO_DEBUG
++	menu->addSeparator();
++	menu->addAction(m_infoViewOnHoverAction);
++#endif
++
++    connect(menu, SIGNAL(aboutToShow()), this, SLOT(updateWireMenu()));
++
++	return menu;
++}
++
++QMenu *MainWindow::schematicWireMenu() {
++	QMenu *menu = new QMenu(QObject::tr("Wire"), this);
++	menu->addMenu(m_zOrderWireMenu);
++	menu->addSeparator();
++	m_schematicWireColorMenu = menu->addMenu(tr("&Wire Color"));
++	foreach(QString colorName, Wire::colorNames) {
++		QString colorValue = Wire::colorTrans.value(colorName);
++        if (colorValue == "white") continue;
++		QAction * action = new QAction(colorName, this);
++		m_schematicWireColorMenu->addAction(action);
++		action->setData(colorValue);
++		action->setCheckable(true);
++		connect(action, SIGNAL(triggered(bool)), this, SLOT(changeWireColor(bool)));
++	}
++	menu->addAction(m_createTraceWireAct);
++	menu->addAction(m_excludeFromAutorouteWireAct);
++	menu->addSeparator();
++	menu->addAction(m_deleteWireAct);
++	menu->addAction(m_deleteWireMinusAct);
++	menu->addSeparator();
++	menu->addAction(m_addBendpointAct);
++#ifndef QT_NO_DEBUG
++	menu->addSeparator();
++	menu->addAction(m_infoViewOnHoverAction);
++#endif
++
++    connect( menu, SIGNAL(aboutToShow()), this, SLOT(updateWireMenu()));
++
++	return menu;
++}
++
++QMenu *MainWindow::viewItemMenuAux(QMenu* menu) {
++	menu->addMenu(m_zOrderMenu);
++	menu->addAction(m_moveLockAct);
++	menu->addAction(m_stickyAct);
++	menu->addSeparator();
++	menu->addAction(m_copyAct);
++	menu->addAction(m_duplicateAct);
++	menu->addAction(m_deleteAct);
++	menu->addAction(m_deleteMinusAct);
++#ifndef QT_NO_DEBUG
++	menu->addSeparator();
++	menu->addAction(m_disconnectAllAct);
++#endif
++	menu->addSeparator();
++	menu->addAction(m_openInPartsEditorNewAct);
++	menu->addMenu(m_addToBinMenu);
++	menu->addSeparator();
++	menu->addAction(m_showPartLabelAct);
++#ifndef QT_NO_DEBUG
++	menu->addSeparator();
++	menu->addAction(m_infoViewOnHoverAction);
++	menu->addAction(m_exportNormalizedSvgAction);
++	menu->addAction(m_exportNormalizedFlattenedSvgAction);
++#endif
++
++    connect(
++    	menu,
++    	SIGNAL(aboutToShow()),
++    	this,
++    	SLOT(updatePartMenu())
++    );
++
++    return menu;
++}
++
++void MainWindow::changeWireColor(bool checked) {
++	if (checked == false) {
++		// choosing the same color again (assuming this action can only apply to a single wire at a time)
++		return;
++	}
++
++	QAction * action = qobject_cast<QAction *>(sender());
++	if (action == NULL) return;
++
++	QString colorName = action->data().toString();
++	if (colorName.isEmpty()) return;
++
++	m_currentGraphicsView->changeWireColor(colorName);
++}
++
++void MainWindow::startSaveInstancesSlot(const QString & fileName, ModelPart *, QXmlStreamWriter & streamWriter) {
++	Q_UNUSED(fileName);
++
++	if (m_backingUp) {
++		streamWriter.writeTextElement("originalFileName", m_fwFilename);
++	}
++
++    if (m_pcbGraphicsView) {
++        QList<ItemBase *> boards = m_pcbGraphicsView->findBoard();
++        if (boards.count()) {
++            streamWriter.writeStartElement("boards");
++            foreach (ItemBase * board, boards) {
++                QRectF r = board->sceneBoundingRect();
++                double w = 2.54 * r.width() / GraphicsUtils::SVGDPI;
++                double h = 2.54 * r.height() / GraphicsUtils::SVGDPI;
++                streamWriter.writeStartElement("board");
++                streamWriter.writeAttribute("moduleId", QString("%1").arg(board->moduleID()));
++                streamWriter.writeAttribute("title", QString("%1").arg(board->title()));
++                streamWriter.writeAttribute("instance", QString("%1").arg(board->instanceTitle()));
++                streamWriter.writeAttribute("width", QString("%1cm").arg(w));
++                streamWriter.writeAttribute("height", QString("%1cm").arg(h));
++                streamWriter.writeEndElement();
++            }
++            streamWriter.writeEndElement();
++        }
++    }
++
++	if (m_linkedProgramFiles.count() > 0) {
++		streamWriter.writeStartElement("programs");
++		QSettings settings;
++		streamWriter.writeAttribute("pid", settings.value("pid").toString());
++		foreach (LinkedFile * linkedFile, m_linkedProgramFiles) {
++			streamWriter.writeStartElement("program");
++			streamWriter.writeAttribute("language", linkedFile->language);
++			streamWriter.writeAttribute("programmer", linkedFile->programmer);
++			streamWriter.writeCharacters(linkedFile->linkedFilename);
++			streamWriter.writeEndElement();
++		}
++		streamWriter.writeEndElement();
++	}
++
++	streamWriter.writeStartElement("views");
++	QList<SketchWidget *> views;
++	views << m_breadboardGraphicsView << m_schematicGraphicsView << m_pcbGraphicsView;
++	foreach  (SketchWidget * sketchWidget, views) {
++		streamWriter.writeStartElement("view");
++		streamWriter.writeAttribute("name", ViewLayer::viewIDXmlName(sketchWidget->viewID()));
++		streamWriter.writeAttribute("backgroundColor", sketchWidget->background().name());
++		streamWriter.writeAttribute("gridSize", sketchWidget->gridSizeText());
++		streamWriter.writeAttribute("showGrid", sketchWidget->showingGrid() ? "1" : "0");
++		streamWriter.writeAttribute("alignToGrid", sketchWidget->alignedToGrid() ? "1" : "0");
++		streamWriter.writeAttribute("viewFromBelow", sketchWidget->viewFromBelow() ? "1" : "0");
++        QHash<QString, QString> autorouterSettings = sketchWidget->getAutorouterSettings();
++        foreach (QString key, autorouterSettings.keys()) {
++		    streamWriter.writeAttribute(key, autorouterSettings.value(key));
++        }
++		streamWriter.writeEndElement();
++	}
++	streamWriter.writeEndElement();
++}
++
++void MainWindow::obsoleteSMDOrientationSlot() {
++    m_obsoleteSMDOrientation = true;    
++}
++
++void MainWindow::loadedRootSlot(const QString & fname, ModelBase *, QDomElement & root) {
++	if (root.isNull()) return;
++
++	QDomElement programs = root.firstChildElement("programs");
++	if (programs.isNull()) return;
++
++	QString thatPid = programs.attribute("pid");
++	QSettings settings;
++	QString thisPid = settings.value("pid").toString();
++	bool sameMachine = thatPid.isEmpty() || (!thisPid.isEmpty() && (thatPid.compare(thisPid) == 0));
++	QFileInfo fileInfo(fname);
++	QDir dir = fileInfo.absoluteDir();
++
++	QDomElement program = programs.firstChildElement("program");
++	while (!program.isNull()) {
++		bool obsolete = false;
++		bool inBundle = false;
++		QString text;
++		TextUtils::findText(program, text);
++		if (!text.isEmpty()) {
++			QString language = program.attribute("language");
++			QString programmer = program.attribute("programmer");
++			QString path;
++			if (thatPid.isEmpty()) {
++				// pre 0.7.0 relative path
++				QFileInfo newFileInfo(text);
++				dir.cd(newFileInfo.dir().path());
++				path = dir.absoluteFilePath(newFileInfo.fileName());
++				obsolete = true;
++			}
++			else {
++				path = text;
++			}
++
++			LinkedFile * linkedFile = new LinkedFile;
++			QFileInfo info(path);
++			if (!(sameMachine && info.exists())) {
++				inBundle = true;
++				path = dir.absoluteFilePath(info.fileName());
++			}
++			linkedFile->linkedFilename = path;
++			linkedFile->language = language;
++			linkedFile->programmer = programmer;
++			linkedFile->fileFlags = LinkedFile::NoFlag;
++			if (sameMachine) linkedFile->fileFlags |= LinkedFile::SameMachineFlag;
++			if (obsolete) linkedFile->fileFlags |= LinkedFile::ObsoleteFlag;
++			if (inBundle) linkedFile->fileFlags |= LinkedFile::InBundleFlag;
++			if (this->m_readOnly) linkedFile->fileFlags |= LinkedFile::ReadOnlyFlag;
++			
++			m_linkedProgramFiles.append(linkedFile);
++		}
++		program = program.nextSiblingElement("program");
++	}
++
++}
++
++void MainWindow::loadedViewsSlot(ModelBase *, QDomElement & views) {
++	if (views.isNull()) return;
++
++	QDomElement view = views.firstChildElement("view");
++	while (!view.isNull()) {
++		QString name = view.attribute("name");
++		ViewLayer::ViewID viewID = ViewLayer::idFromXmlName(name);
++        SketchWidget * sketchWidget = NULL;
++		switch (viewID) {
++			case ViewLayer::BreadboardView:
++				sketchWidget = m_breadboardGraphicsView;
++				break;
++			case ViewLayer::SchematicView:
++				sketchWidget = m_schematicGraphicsView;
++				break;
++			case ViewLayer::PCBView:
++				sketchWidget = m_pcbGraphicsView;
++				break;
++			default:
++				break;
++		}
++
++        if (sketchWidget) {
++		    QString colorName = view.attribute("backgroundColor", "");
++            QString gridSizeText = view.attribute("gridSize", "");
++            QString alignToGridText = view.attribute("alignToGrid", "");
++            QString showGridText = view.attribute("showGrid", "");
++            QString viewFromBelowText = view.attribute("viewFromBelow", "");
++            
++            QHash<QString, QString> autorouterSettings;
++            QDomNamedNodeMap map = view.attributes();
++            for (int m = 0; m < map.count(); m++) {
++			    QDomNode node = map.item(m);
++			    autorouterSettings.insert(node.nodeName(), node.nodeValue());
++            }
++            sketchWidget->setAutorouterSettings(autorouterSettings);
++
++		    QColor color;
++		    color.setNamedColor(colorName);
++
++            bool redraw = false;
++            if (color.isValid()) {
++                sketchWidget->setBackground(color);
++                redraw = true;
++            }
++            if (!alignToGridText.isEmpty()) {
++                sketchWidget->alignToGrid(alignToGridText.compare("1") == 0);
++            }
++            if (!showGridText.isEmpty()) {
++                sketchWidget->showGrid(showGridText.compare("1") == 0);
++                redraw = 1;
++            }
++            if (!gridSizeText.isEmpty()) {
++                sketchWidget->setGridSize(gridSizeText);
++                redraw = true;
++            }
++
++            if (!viewFromBelowText.isEmpty()) {
++                sketchWidget->setViewFromBelow(viewFromBelowText.compare("1") == 0);
++                redraw = 1;
++            }
++
++            if (redraw) sketchWidget->invalidateScene();
++        }
++
++		view = view.nextSiblingElement("view");
++	}
++}
++
++void MainWindow::disconnectAll() {
++	m_currentGraphicsView->disconnectAll();
++}
++
++bool MainWindow::externalProcess(QString & name, QString & path, QStringList & args) {
++	emit externalProcessSignal(name, path, args);
++
++	if (path.isEmpty()) return false;
++
++	if (name.isEmpty()) {
++		name = tr("Launch %1...").arg(path);
++	}
++
++	return true;
++}
++
++void MainWindow::launchExternalProcess() {
++	QString name;
++	QString path;
++	QStringList args;
++	if (!externalProcess(name, path, args)) return;
++
++	args.append("-sketch");
++	args.append(fileName());
++	m_externalProcessOutput.clear();
++
++	QFileInfo f = QFileInfo(path);
++	QProcess * process = new QProcess(this);
++	process->setWorkingDirectory(f.dir().absolutePath());
++	process->setProcessChannelMode(QProcess::MergedChannels);
++	process->setReadChannel(QProcess::StandardOutput);
++
++	connect(process, SIGNAL(error(QProcess::ProcessError)), this, SLOT(processError(QProcess::ProcessError)));
++	connect(process, SIGNAL(finished(int, QProcess::ExitStatus)), this, SLOT(processFinished(int, QProcess::ExitStatus)));
++	connect(process, SIGNAL(readyReadStandardOutput()), this, SLOT(processReadyRead()));
++	connect(process, SIGNAL(stateChanged(QProcess::ProcessState)), this, SLOT(processStateChanged(QProcess::ProcessState)));
++
++	process->start(path, args);
++}
++
++
++void MainWindow::processError(QProcess::ProcessError processError) {
++	DebugDialog::debug(QString("process error %1").arg(processError));
++}
++
++void MainWindow::processFinished(int exitCode, QProcess::ExitStatus exitStatus) {
++	DebugDialog::debug(QString("process finished %1 %2").arg(exitCode).arg(exitStatus));
++
++	QString name, path;
++	QStringList args;
++	externalProcess(name, path, args);
++	QMessageBox::information(this, name, QString(m_externalProcessOutput));
++
++	sender()->deleteLater();
++}
++
++void MainWindow::processReadyRead() {
++	QByteArray byteArray = qobject_cast<QProcess *>(sender())->readAllStandardOutput();
++	m_externalProcessOutput.append(byteArray);
++
++	DebugDialog::debug(byteArray.data());
++}
++
++void MainWindow::processStateChanged(QProcess::ProcessState newState) {
++	switch(newState) {
++		case QProcess::Running:
++			DebugDialog::debug(QString("process running"));
++			break;
++		case QProcess::Starting:
++			DebugDialog::debug(QString("process starting"));
++			break;
++		case QProcess::NotRunning:
++			DebugDialog::debug(QString("process not running"));
++			break;
++	}
++}
++
++void MainWindow::shareOnline() {
++	QDesktopServices::openUrl(QString("http://fritzing.org/projects/create/"));
++}
++
++
++void MainWindow::selectAllObsolete() {
++	selectAllObsolete(true);
++}
++
++void MainWindow::selectAllObsolete(bool displayFeedback) {
++	int obs = m_currentGraphicsView->selectAllObsolete();
++	if (!displayFeedback) return;
++
++	if (obs <= 0) {
++        QMessageBox::information(this, tr("Fritzing"), tr("No outdated parts found.\nAll your parts are up-to-date.") );
++    } 
++	else {
++        QMessageBox::StandardButton answer = QMessageBox::question(
++                this,
++                tr("Outdated parts"),
++                tr("Found %n outdated parts. Do you want to update them now?", "", obs),
++                QMessageBox::Yes | QMessageBox::No,
++                QMessageBox::Yes
++        );
++        // TODO: make button texts translatable
++        if (answer == QMessageBox::Yes) {
++            swapObsolete();
++        }
++	}
++}
++
++ModelPart * MainWindow::findReplacedby(ModelPart * originalModelPart) {
++	ModelPart * newModelPart = originalModelPart;
++	while (true) {
++		QString newModuleID = newModelPart->replacedby();
++		if (newModuleID.isEmpty()) {
++			return ((newModelPart == originalModelPart) ? NULL : newModelPart);
++		}
++
++		ModelPart * tempModelPart = this->m_referenceModel->retrieveModelPart(newModuleID);
++		if (tempModelPart == NULL) {
++			// something's screwy
++			return NULL;
++		}
++
++		newModelPart = tempModelPart;
++	}
++}
++
++void MainWindow::swapObsolete() {
++	swapObsolete(true);
++}
++
++void MainWindow::swapObsolete(bool displayFeedback) {
++
++	QSet<ItemBase *> itemBases;
++	foreach (QGraphicsItem * item, m_currentGraphicsView->scene()->selectedItems()) {
++		ItemBase * itemBase = dynamic_cast<ItemBase *>(item);
++		if (itemBase == NULL) continue;
++		if (!itemBase->isObsolete()) continue;
++
++		itemBase = itemBase->layerKinChief();
++		itemBases.insert(itemBase);
++	}
++
++	if (itemBases.count() <= 0) return;
++
++	QUndoCommand* parentCommand = new QUndoCommand();
++    int count = 0;
++    QMap<QString, QString> propsMap;
++	foreach (ItemBase * itemBase, itemBases) {
++		ModelPart * newModelPart = findReplacedby(itemBase->modelPart());
++		if (newModelPart == NULL) {
++			QMessageBox::information(
++				this,
++				tr("Sorry!"),
++				tr( "unable to find replacement for %1.\n").arg(itemBase->title())
++			);
++			continue;
++		}
++
++		count++;
++		long newID = swapSelectedAuxAux(itemBase, newModelPart->moduleID(), itemBase->viewLayerPlacement(), propsMap, parentCommand);
++		if (itemBase->modelPart()) {
++			// special case for swapping old resistors.
++			QString resistance = itemBase->modelPart()->properties().value("resistance", "");
++			if (!resistance.isEmpty()) {
++				QChar r = resistance.at(resistance.length() - 1);
++				ushort ohm = r.unicode();
++				if (ohm == 8486) {
++					// ends with the ohm symbol
++					resistance.chop(1);
++				}
++			}
++			QString footprint = itemBase->modelPart()->properties().value("footprint", "");
++			if (!resistance.isEmpty() && !footprint.isEmpty()) {
++				new SetResistanceCommand(m_currentGraphicsView, newID, resistance, resistance, footprint, footprint, parentCommand);
++			}
++
++			// special case for swapping LEDs
++			if (newModelPart->moduleID().contains(ModuleIDNames::ColorLEDModuleIDName)) {
++				QString oldColor = itemBase->modelPart()->properties().value("color");
++				QString newColor;
++				if (oldColor.contains("red", Qt::CaseInsensitive)) {
++					newColor = "Red (633nm)";
++				}
++				else if (oldColor.contains("blue", Qt::CaseInsensitive)) {
++					newColor = "Blue (430nm)";
++				}
++				else if (oldColor.contains("yellow", Qt::CaseInsensitive)) {
++					newColor = "Yellow (585nm)";
++				}
++				else if (oldColor.contains("green", Qt::CaseInsensitive)) {
++					newColor = "Green (555nm)";
++				}
++				else if (oldColor.contains("white", Qt::CaseInsensitive)) {
++					newColor = "White (4500K)";
++				}
++
++				if (newColor.length() > 0) {
++					new SetPropCommand(m_currentGraphicsView, newID, "color", newColor, newColor, true, parentCommand);
++				}
++			}
++
++		}
++	}
++
++
++	if (count == 0) {
++		delete parentCommand;
++	}
++	else {
++        parentCommand->setText(tr("Update %1 part(s)", "").arg(count));
++		m_undoStack->push(parentCommand);
++	}
++
++	if (displayFeedback) {
++		QMessageBox::information(this, tr("Fritzing"), tr("Successfully updated %1 part(s).\n"
++                                                          "Please check all views for potential side-effects.").arg(count) );
++	}
++	DebugDialog::debug(QString("updated %1 obsolete in %2").arg(count).arg(m_fwFilename));
++}
++
++void MainWindow::throwFakeException() {
++    throw "fake exception";
++}
++
++void MainWindow::alignToGrid() {
++	if (m_currentGraphicsView == NULL) return;
++
++	m_currentGraphicsView->alignToGrid(m_alignToGridAct->isChecked());
++    setWindowModified(true);
++}
++
++void MainWindow::showGrid() {
++	if (m_currentGraphicsView == NULL) return;
++
++	m_currentGraphicsView->showGrid(m_showGridAct->isChecked());
++    setWindowModified(true);
++}
++
++void MainWindow::setGridSize() 
++{
++    GridSizeThing gridSizeThing(m_currentGraphicsView->viewName(), 
++                                m_currentGraphicsView->getShortName(), 
++                                m_currentGraphicsView->defaultGridSizeInches(),
++                                m_currentGraphicsView->gridSizeText());
++
++    GridSizeDialog dialog(&gridSizeThing);
++    dialog.setWindowTitle(QObject::tr("Set Grid Size"));
++
++	QVBoxLayout * vLayout = new QVBoxLayout(&dialog);
++
++    vLayout->addWidget(createGridSizeForm(&gridSizeThing));
++
++    QDialogButtonBox * buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
++	buttonBox->button(QDialogButtonBox::Cancel)->setText(tr("Cancel"));
++	buttonBox->button(QDialogButtonBox::Ok)->setText(tr("OK"));
++
++    connect(buttonBox, SIGNAL(accepted()), &dialog, SLOT(accept()));
++    connect(buttonBox, SIGNAL(rejected()), &dialog, SLOT(reject()));
++
++	vLayout->addWidget(buttonBox);
++
++    int result = dialog.exec();
++
++    if (result == QDialog::Accepted) {
++	    QString units = (gridSizeThing.inButton->isChecked() ? "in" : "mm");
++        m_currentGraphicsView->setGridSize(gridSizeThing.lineEdit->text() + units);
++        setWindowModified(true);
++    }
++}
++
++QWidget * MainWindow::createGridSizeForm(GridSizeThing * gridSizeThing)
++{
++	QGroupBox * over = new QGroupBox("", this);
++
++	QVBoxLayout * vLayout = new QVBoxLayout();
++
++	QLabel * explain = new QLabel(tr("Set the grid size for %1.").arg(gridSizeThing->viewName));
++	vLayout->addWidget(explain);
++
++	QGroupBox * groupBox = new QGroupBox(this);
++
++	QHBoxLayout * hLayout = new QHBoxLayout();
++
++	QLabel * label = new QLabel(tr("Grid Size:"));
++	hLayout->addWidget(label);
++
++	gridSizeThing->lineEdit = new QLineEdit();
++	
++	gridSizeThing->lineEdit->setFixedWidth(45);
++
++	gridSizeThing->validator = new QDoubleValidator(gridSizeThing->lineEdit);
++	gridSizeThing->validator->setRange(0.001, 1.0, 3);
++	gridSizeThing->validator->setNotation(QDoubleValidator::StandardNotation);
++	gridSizeThing->lineEdit->setValidator(gridSizeThing->validator);
++
++	hLayout->addWidget(gridSizeThing->lineEdit);
++
++	gridSizeThing->inButton = new QRadioButton(tr("in"), this); 
++	hLayout->addWidget(gridSizeThing->inButton);
++
++	gridSizeThing->mmButton = new QRadioButton(tr("mm"), this); 
++	hLayout->addWidget(gridSizeThing->mmButton);
++
++	groupBox->setLayout(hLayout);
++
++	vLayout->addWidget(groupBox);
++	vLayout->addSpacing(5);
++
++	QPushButton * pushButton = new QPushButton(this);
++	pushButton->setText(tr("Restore Default"));
++	pushButton->setMaximumWidth(115);
++	vLayout->addWidget(pushButton);
++	vLayout->addSpacing(10);
++
++	over->setLayout(vLayout);
++
++	if (gridSizeThing->gridSizeText.length() <= 2) {
++		gridSizeThing->inButton->setChecked(true);
++		gridSizeThing->lineEdit->setText(QString::number(gridSizeThing->defaultGridSize));
++	}
++	else {
++		if (gridSizeThing->gridSizeText.endsWith("mm")) {
++			gridSizeThing->mmButton->setChecked(true);
++			gridSizeThing->validator->setTop(25.4);
++		}
++		else {
++			gridSizeThing->inButton->setChecked(true);
++		}
++        QString szString = gridSizeThing->gridSizeText;
++		szString.chop(2);
++		gridSizeThing->lineEdit->setText(szString);
++	}
++
++	connect(gridSizeThing->inButton, SIGNAL(clicked(bool)), this, SLOT(gridUnits(bool)));
++	connect(pushButton, SIGNAL(clicked()), this, SLOT(restoreDefaultGrid()));
++	connect(gridSizeThing->mmButton, SIGNAL(clicked(bool)), this, SLOT(gridUnits(bool)));
++
++	return over;
++}
++
++
++void MainWindow::openProgramWindow() {
++	if (m_programWindow) {
++		m_programWindow->setVisible(true);
++		m_programWindow->raise();
++		return;
++	}
++
++	m_programWindow = new ProgramWindow();
++	connect(m_programWindow, SIGNAL(linkToProgramFile(const QString &, const QString &, const QString &, bool, bool)), 
++			this, SLOT(linkToProgramFile(const QString &, const QString &, const QString &, bool, bool)));
++	connect(m_programWindow, SIGNAL(changeActivationSignal(bool, QWidget *)), qApp, SLOT(changeActivation(bool, QWidget *)), Qt::DirectConnection);
++	connect(m_programWindow, SIGNAL(destroyed(QObject *)), qApp, SLOT(topLevelWidgetDestroyed(QObject *)));
++
++	QFileInfo fileInfo(m_fwFilename);
++	m_programWindow->setup();
++	m_programWindow->linkFiles(m_linkedProgramFiles, fileInfo.absoluteDir().absolutePath());
++	m_programWindow->setVisible(true);
++}
++
++void MainWindow::linkToProgramFile(const QString & filename, const QString & language, const QString & programmer, bool addLink, bool strong) {
++#ifdef Q_WS_WIN
++	Qt::CaseSensitivity sensitivity = Qt::CaseInsensitive;
++#else
++	Qt::CaseSensitivity sensitivity = Qt::CaseSensitive;
++#endif
++
++	if (addLink && strong) {
++		bool gotOne = false;
++		foreach (LinkedFile * linkedFile, m_linkedProgramFiles) {
++			if (linkedFile->linkedFilename.compare(filename, sensitivity) == 0) {
++				if (linkedFile->language != language) {
++					linkedFile->language = language;
++					this->setWindowModified(true);
++				}
++				if (linkedFile->programmer != programmer) {
++					linkedFile->programmer = programmer;
++					this->setWindowModified(true);
++				}
++				gotOne = true;
++				break;
++			}
++		}
++		if (!gotOne) {
++			LinkedFile * linkedFile = new LinkedFile;
++			linkedFile->linkedFilename = filename;
++			linkedFile->language = language;
++			linkedFile->programmer = programmer;
++			m_linkedProgramFiles.append(linkedFile);
++			this->setWindowModified(true);
++		}
++		return;
++	}
++	else {
++		for (int i = 0; i < m_linkedProgramFiles.count(); i++) {
++			LinkedFile * linkedFile = m_linkedProgramFiles.at(i);
++			if (linkedFile->linkedFilename.compare(filename, sensitivity) == 0) {
++				if (strong) {
++					m_linkedProgramFiles.removeAt(i);
++					this->setWindowModified(true);
++				}
++				else {
++					if (linkedFile->language != language) {
++						linkedFile->language = language;
++						this->setWindowModified(true);
++					}
++					if (linkedFile->programmer != programmer) {
++						linkedFile->programmer = programmer;
++						this->setWindowModified(true);
++					}
++				}
++				return;
++			}
++		}
++	}
++}
++
++QStringList MainWindow::newDesignRulesCheck() 
++{
++    return newDesignRulesCheck(true);
++}
++
++QStringList MainWindow::newDesignRulesCheck(bool showOkMessage) 
++{
++    QStringList results;
++
++	if (m_currentGraphicsView == NULL) return results;
++
++	PCBSketchWidget * pcbSketchWidget = qobject_cast<PCBSketchWidget *>(m_currentGraphicsView);
++	if (pcbSketchWidget == NULL) return results;
++	
++    ItemBase * board = NULL;
++    if (pcbSketchWidget->autorouteTypePCB()) {
++        int boardCount;
++		board = pcbSketchWidget->findSelectedBoard(boardCount);
++        if (boardCount == 0) {
++            QString message = tr("Your sketch does not have a board yet! DRC only works with a PCB.");
++            results << message;
++            QMessageBox::critical(this, tr("Fritzing"), message);
++            return results;
++        }
++        if (board == NULL) {
++            QString message = tr("Please select a PCB. DRC only works on one board at a time.");
++            results << message;
++            QMessageBox::critical(this, tr("Fritzing"), message);
++            return results;
++        }
++	}
++
++	bool copper0Active = pcbSketchWidget->layerIsActive(ViewLayer::Copper0);
++	bool copper1Active = pcbSketchWidget->layerIsActive(ViewLayer::Copper1);
++
++	AutorouteProgressDialog progress(tr("DRC Progress..."), true, false, false, false, pcbSketchWidget, this);
++	progress.setModal(true);
++	progress.show();
++	QRect pr = progress.frameGeometry();
++	QRect wr = pcbSketchWidget->frameGeometry();
++    QPoint p = pcbSketchWidget->mapTo(this, wr.topRight());
++	progress.move(p.x() - pr.width(), pr.top());
++
++	DRC drc(pcbSketchWidget, board);
++
++	connect(&drc, SIGNAL(wantTopVisible()), this, SLOT(activeLayerTop()), Qt::DirectConnection);
++	connect(&drc, SIGNAL(wantBottomVisible()), this, SLOT(activeLayerBottom()), Qt::DirectConnection);
++	connect(&drc, SIGNAL(wantBothVisible()), this, SLOT(activeLayerBoth()), Qt::DirectConnection);
++
++	connect(&progress, SIGNAL(cancel()), &drc, SLOT(cancel()), Qt::DirectConnection);
++
++	connect(&drc, SIGNAL(setMaximumProgress(int)), &progress, SLOT(setMaximum(int)), Qt::DirectConnection);
++	connect(&drc, SIGNAL(setProgressValue(int)), &progress, SLOT(setValue(int)), Qt::DirectConnection);
++	connect(&drc, SIGNAL(setProgressMessage(const QString &)), &progress, SLOT(setMessage(const QString &)));
++	connect(&drc, SIGNAL(setProgressMessage2(const QString &)), &progress, SLOT(setMessage2(const QString &)));
++	connect(&drc, SIGNAL(hideProgress()), &progress, SLOT(close()));
++
++	ProcessEventBlocker::processEvents();
++	ProcessEventBlocker::block();
++	results = drc.start(showOkMessage, pcbSketchWidget->getKeepout() * 1000 / GraphicsUtils::SVGDPI);     // pixels to mils
++	ProcessEventBlocker::unblock();
++
++	pcbSketchWidget->setLayerActive(ViewLayer::Copper1, copper1Active);
++	pcbSketchWidget->setLayerActive(ViewLayer::Silkscreen1, copper1Active);
++	pcbSketchWidget->setLayerActive(ViewLayer::Copper0, copper0Active);
++	pcbSketchWidget->setLayerActive(ViewLayer::Silkscreen0, copper0Active);
++	updateActiveLayerButtons();
++    return results;
++}
++
++void MainWindow::changeTraceLayer() {
++	if (m_currentGraphicsView == NULL) return;
++	if (m_currentGraphicsView != m_pcbGraphicsView) return;
++
++	Wire * wire = retrieveWire();
++	m_pcbGraphicsView->changeTraceLayer(wire, false, NULL);
++}
++
++Wire * MainWindow::retrieveWire() {
++	WireAction * wireAction = qobject_cast<WireAction *>(sender());
++	if (wireAction == NULL) return NULL;
++
++	return wireAction->wire();
++}
++
++ConnectorItem * MainWindow::retrieveConnectorItem() {
++	ConnectorItemAction * connectorItemAction = qobject_cast<ConnectorItemAction *>(sender());
++	if (connectorItemAction == NULL) return NULL;
++
++	return connectorItemAction->connectorItem();
++}
++
++void MainWindow::setSticky()
++{
++    QList<QGraphicsItem *> items = m_currentGraphicsView->scene()->selectedItems();
++    if (items.count() < 1) return;
++
++    ItemBase * itemBase = dynamic_cast<ItemBase *>(items.at(0));
++    if (itemBase == NULL) return;
++
++    if (!itemBase->isBaseSticky()) return;
++
++    itemBase->setLocalSticky(!itemBase->isLocalSticky()); 
++}
++
++void MainWindow::moveLock()
++{
++	bool moveLock = true;
++	
++	foreach (QGraphicsItem  * item, m_currentGraphicsView->scene()->selectedItems()) {
++		ItemBase * itemBase = ItemBase::extractTopLevelItemBase(item);
++		if (itemBase == NULL) continue;
++		if (itemBase->itemType() == ModelPart::Wire) continue;
++
++		if (itemBase->moveLock()) {
++			moveLock = false;
++			break;
++		}
++	}
++
++	ItemBase * viewedItem = m_infoView->currentItem();
++	foreach (QGraphicsItem  * item, m_currentGraphicsView->scene()->selectedItems()) {
++		ItemBase * itemBase = ItemBase::extractTopLevelItemBase(item);
++		if (itemBase == NULL) continue;
++		if (itemBase->itemType() == ModelPart::Wire) continue;
++		
++		itemBase->setMoveLock(moveLock);
++		if (viewedItem && viewedItem->layerKinChief() == itemBase->layerKinChief()) {
++			m_currentGraphicsView->viewItemInfo(itemBase);
++		}
++	}
++}
++
++void MainWindow::selectMoveLock()
++{
++	m_currentGraphicsView->selectAllMoveLock();
++}
++
++void MainWindow::autorouterSettings() {
++	if (m_currentGraphicsView != m_pcbGraphicsView) return;
++
++	m_pcbGraphicsView->autorouterSettings();
++}
++
++void MainWindow::orderFab() 
++{
++	QDesktopServices::openUrl(QString("http://fab.fritzing.org/"));
++}
++
++void MainWindow::setGroundFillSeeds() {
++    int boardCount;
++    ItemBase * board = m_pcbGraphicsView->findSelectedBoard(boardCount);
++    if (boardCount == 0) {
++        QMessageBox::critical(this, tr("Fritzing"),
++                   tr("Your sketch does not have a board yet! Please add a PCB in order to use copper fill operations."));
++        return;
++    }
++    if (board == NULL) {
++        QMessageBox::critical(this, tr("Fritzing"),
++                   tr("Please select a PCB. Copper fill operations only work on one board at a time."));
++        return;
++    }
++
++	m_pcbGraphicsView->setGroundFillSeeds();
++}
++
++void MainWindow::clearGroundFillSeeds() {
++    int boardCount;
++    ItemBase * board = m_pcbGraphicsView->findSelectedBoard(boardCount);
++    if (boardCount == 0) {
++        QMessageBox::critical(this, tr("Fritzing"),
++                   tr("Your sketch does not have a board yet! Please add a PCB in order to use copper fill operations."));
++        return;
++    }
++    if (board == NULL) {
++        QMessageBox::critical(this, tr("Fritzing"),
++                   tr("Please select a PCB. Copper fill operations only work on one board at a time."));
++        return;
++    }
++
++    m_pcbGraphicsView->clearGroundFillSeeds();
++}
++
++void MainWindow::setOneGroundFillSeed() {
++	ConnectorItemAction * action = qobject_cast<ConnectorItemAction *>(sender());
++	if (action == NULL) return;
++
++	ConnectorItem * connectorItem = action->connectorItem();
++	if (connectorItem == NULL) return;
++
++	GroundFillSeedCommand * command = new GroundFillSeedCommand(m_pcbGraphicsView, NULL);
++	command->addItem(connectorItem->attachedToID(), connectorItem->connectorSharedID(), action->isChecked());
++
++	m_undoStack->push(command);
++}
++
++void MainWindow::gridUnits(bool checked) {
++    QWidget * widget = qobject_cast<QWidget *>(sender());
++    if (widget == NULL) return;
++
++    GridSizeDialog * dialog = qobject_cast<GridSizeDialog *>(widget->window());
++    if (dialog == NULL) return;
++
++	GridSizeThing * gridSizeThing = dialog->gridSizeThing();
++
++	QString units;
++	if (sender() == gridSizeThing->inButton) {
++		units = (checked) ? "in" : "mm";
++	}
++	else {
++		units = (checked) ? "mm" : "in";
++	}
++	
++	if (units.startsWith("mm")) {
++		gridSizeThing->validator->setTop(25.4);
++		gridSizeThing->lineEdit->setText(QString::number(gridSizeThing->lineEdit->text().toDouble() * 25.4));
++	}
++	else {
++		gridSizeThing->validator->setTop(1.0);
++		gridSizeThing->lineEdit->setText(QString::number(gridSizeThing->lineEdit->text().toDouble() / 25.4));
++	}
++
++}
++
++void MainWindow::restoreDefaultGrid() {
++    QWidget * widget = qobject_cast<QWidget *>(sender());
++    if (widget == NULL) return;
++
++    GridSizeDialog * dialog = qobject_cast<GridSizeDialog *>(widget->window());
++    if (dialog == NULL) return;
++
++	GridSizeThing * gridSizeThing = dialog->gridSizeThing();
++
++	gridSizeThing->inButton->setChecked(true);
++	gridSizeThing->mmButton->setChecked(false);
++	gridSizeThing->lineEdit->setText(QString::number(gridSizeThing->defaultGridSize));
++}
++
++void MainWindow::setBackgroundColor()
++{
++	QColor cc = m_currentGraphicsView->background();
++	QColor scc = m_currentGraphicsView->standardBackground();
++
++	SetColorDialog setColorDialog(tr("%1 background Color").arg(m_currentGraphicsView->viewName()), cc, scc, true, this);
++	int result = setColorDialog.exec();
++	if (result == QDialog::Rejected) return;
++
++	QColor newColor = setColorDialog.selectedColor();
++    m_currentGraphicsView->setBackgroundColor(newColor, setColorDialog.isPrefsColor());
++    setWindowModified(true);
++}
++
++void MainWindow::checkLoadedTraces() {
++    if (m_pcbGraphicsView) m_pcbGraphicsView->checkLoadedTraces();
++}
++
++void MainWindow::showUnrouted() 
++{
++    m_currentGraphicsView->showUnrouted();
++}
++
++void MainWindow::hidePartSilkscreen()
++{
++    m_pcbGraphicsView->hidePartSilkscreen();
++}
++
++void MainWindow::fabQuote() {
++    if (m_pcbGraphicsView) m_pcbGraphicsView->fabQuote();
++}
++
++void MainWindow::findPartInSketch() {
++    static QString lastSearchText;
++
++	if (m_currentGraphicsView == NULL) return;
++
++    bool ok;
++    QString text = QInputDialog::getText(this, tr("Enter Text"),
++                                          tr("Text will match part label, description, title, etc. Enter text to search for:"), 
++                                          QLineEdit::Normal, lastSearchText, &ok);
++    if (!ok || text.isEmpty()) return;
++
++    lastSearchText = text;
++    QSet<ItemBase *> itemBases;
++    foreach (QGraphicsItem * item, m_currentGraphicsView->scene()->items()) {
++        ItemBase * itemBase = dynamic_cast<ItemBase *>(item);
++        if (itemBase == NULL) continue;
++
++        itemBases.insert(itemBase->layerKinChief());
++    }
++
++	QStringList strings;
++    strings << text;
++    QList<ItemBase *> matched;
++    foreach (ItemBase * itemBase, itemBases) {
++
++#ifndef QT_NO_DEBUG
++        if (QString::number(itemBase->id()).contains(text)) {
++            matched << itemBase;
++            continue;
++        }
++#endif
++
++        if (itemBase->instanceTitle().contains(text, Qt::CaseInsensitive)) {
++            matched << itemBase;
++            continue;
++        }
++
++	    QList<ModelPart *> modelParts;
++        m_referenceModel->search(itemBase->modelPart(), strings, modelParts, true);
++        if (modelParts.count() > 0) {
++            matched << itemBase;
++        }
++    }
++
++    if (matched.count() == 0) {
++	    QMessageBox::information(this, tr("Search"), tr("No parts matched search term '%1'.").arg(text));
++        return;
++    }
++
++    m_currentGraphicsView->selectItems(matched);
++}
++
++void MainWindow::setGroundFillKeepout() {
++    if (m_pcbGraphicsView != NULL) m_pcbGraphicsView->setGroundFillKeepout();
++}
++
++void MainWindow::setViewFromBelowToggle() {
++    if (m_pcbGraphicsView != NULL) {
++        m_pcbGraphicsView->setViewFromBelow(m_viewFromBelowToggleAct->isChecked());
++        updateActiveLayerButtons();
++    }
++}
++
++void MainWindow::setViewFromBelow() {
++    if (m_pcbGraphicsView != NULL) {
++        m_pcbGraphicsView->setViewFromBelow(true);
++        updateActiveLayerButtons();
++    }
++}
++
++void MainWindow::setViewFromAbove() {
++    if (m_pcbGraphicsView != NULL) {
++        m_pcbGraphicsView->setViewFromBelow(false);
++        updateActiveLayerButtons();
++    }
++}
diff --git a/fritzing.spec b/fritzing.spec
index f385f61..749aa7a 100644
--- a/fritzing.spec
+++ b/fritzing.spec
@@ -1,6 +1,6 @@
 Name:           fritzing
-Version:        0.7.12b
-Release:        3%{?dist}
+Version:        0.8.3b
+Release:        0%{?dist}
 Summary:        Electronic Design Automation software; from prototype to product
 
 Group:          Applications/Engineering
@@ -61,6 +61,9 @@ desktop-file-install --dir=%{buildroot}%{_datadir}/applications %{SOURCE1}
 %{_mandir}/man?/*
 
 %changelog
+* Sat Aug 10 2013 Ed Marshall <esm at logic.net> - 0.8.3b-0
+- Updated to 0.8.3b release.
+
 * Sat Aug 03 2013 Fedora Release Engineering <rel-eng at lists.fedoraproject.org> - 0.7.12b-3
 - Rebuilt for https://fedoraproject.org/wiki/Fedora_20_Mass_Rebuild
 
diff --git a/sources b/sources
index cb8b97d..9955511 100644
--- a/sources
+++ b/sources
@@ -1,2 +1 @@
-4f2d5e0dff6ce83d6f3d68d7408006fe  fritzing-0.7.12b.source.tar.bz2
-cc5b90009ac9dbd1561935fd648b1037  fritzing-0.7.11b.source.tar.bz2
+427ff65d4c0bd75369f211d096f2ed56  fritzing-0.8.3b.source.tar.bz2


More information about the scm-commits mailing list