~ubuntu-branches/ubuntu/trusty/fritzing/trusty-proposed

« back to all changes in this revision

Viewing changes to src/mainwindow.cpp

  • Committer: Package Import Robot
  • Author(s): Enrique Hernández Bello
  • Date: 2012-11-11 21:38:56 UTC
  • mfrom: (1.1.5)
  • Revision ID: package-import@ubuntu.com-20121111213856-0825ywdrtdcshl91
Tags: 0.7.10b-1
* New upstream version. Closes: #661495, #692998
* Removed useless patches.
* Removed SetupAPI.lib from sourceless files.
* Skip dfsg tarball creation if there are no sourceless files.
* Added libqt4-sql-sqlite to dependencies. Thanks to Tom Hummel <tom@bluespice.org>.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*******************************************************************
2
 
 
3
 
Part of the Fritzing project - http://fritzing.org
4
 
Copyright (c) 2007-2012 Fachhochschule Potsdam - http://fh-potsdam.de
5
 
 
6
 
Fritzing is free software: you can redistribute it and/or modify
7
 
 
8
 
it under the terms of the GNU General Public License as published by
9
 
the Free Software Foundation, either version 3 of the License, or
10
 
(at your option) any later version.
11
 
 
12
 
Fritzing is distributed in the hope that it will be useful,
13
 
but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
 
GNU General Public License for more details.
16
 
 
17
 
You should have received a copy of the GNU General Public License
18
 
along with Fritzing.  If not, see <http://www.gnu.org/licenses/>.
19
 
 
20
 
********************************************************************
21
 
 
22
 
$Revision: 6265 $:
23
 
$Author: cohen@irascible.com $:
24
 
$Date: 2012-08-08 04:07:28 +0200 (Wed, 08 Aug 2012) $
25
 
 
26
 
********************************************************************/
27
 
 
28
 
#include <QtGui>
29
 
#include <QtXml>
30
 
#include <QList>
31
 
#include <QFileInfo>
32
 
#include <QStringList>
33
 
#include <QFileInfoList>
34
 
#include <QDir>
35
 
#include <QLabel>
36
 
#include <QTime>
37
 
#include <QSettings>
38
 
#include <QRegExp>
39
 
#include <QPaintDevice>
40
 
#include <QPixmap>
41
 
#include <QTimer>
42
 
#include <QStackedWidget>
43
 
#include <QXmlStreamReader>
44
 
#include <QShortcut>
45
 
 
46
 
#include "mainwindow.h"
47
 
#include "debugdialog.h"
48
 
#include "connectors/connector.h"
49
 
#include "partsbinpalette/partsbinpalettewidget.h"
50
 
#include "fdockwidget.h"
51
 
#include "infoview/htmlinfoview.h"
52
 
#include "waitpushundostack.h"
53
 
#include "layerattributes.h"
54
 
#include "navigator/triplenavigator.h"
55
 
#include "sketch/breadboardsketchwidget.h"
56
 
#include "sketch/schematicsketchwidget.h"
57
 
#include "sketch/pcbsketchwidget.h"
58
 
#include "svg/svgfilesplitter.h"
59
 
#include "utils/folderutils.h"
60
 
#include "utils/lockmanager.h"
61
 
#include "utils/textutils.h"
62
 
#include "utils/graphicsutils.h"
63
 
#include "items/mysterypart.h"
64
 
#include "items/moduleidnames.h"
65
 
#include "items/pinheader.h"
66
 
#include "items/perfboard.h"
67
 
#include "items/stripboard.h"
68
 
#include "items/partfactory.h"
69
 
#include "layerpalette.h"
70
 
#include "items/paletteitem.h"
71
 
#include "items/virtualwire.h"
72
 
#include "items/screwterminal.h"
73
 
#include "items/dip.h"
74
 
#include "processeventblocker.h"
75
 
#include "help/helper.h"
76
 
#include "dockmanager.h"
77
 
 
78
 
#include "partsbinpalette/binmanager/binmanager.h"
79
 
 
80
 
#include "fsvgrenderer.h"
81
 
#include "utils/fsizegrip.h"
82
 
#include "utils/expandinglabel.h"
83
 
#include "viewswitcher/viewswitcher.h"
84
 
#include "viewswitcher/viewswitcherdockwidget.h"
85
 
 
86
 
#include "utils/autoclosemessagebox.h"
87
 
#include "utils/fileprogressdialog.h"
88
 
#include "utils/clickablelabel.h"
89
 
#include "items/resizableboard.h"
90
 
#include "items/resistor.h"
91
 
#include "items/symbolpaletteitem.h"
92
 
#include "utils/zoomslider.h"
93
 
 
94
 
 
95
 
///////////////////////////////////////////////
96
 
 
97
 
#define ZIP_PART QString("part.")
98
 
#define ZIP_SVG  QString("svg.")
99
 
 
100
 
///////////////////////////////////////////////
101
 
 
102
 
// SwapTimer explained: http://code.google.com/p/fritzing/issues/detail?id=1431
103
 
 
104
 
SwapTimer::SwapTimer() : QTimer() 
105
 
{
106
 
}
107
 
 
108
 
void SwapTimer::setAll(const QString & family, const QString & prop, QMap<QString, QString> & propsMap, ItemBase * itemBase)
109
 
{
110
 
        m_family = family;
111
 
        m_prop = prop;
112
 
        m_propsMap = propsMap;
113
 
        m_itemBase = itemBase;
114
 
}
115
 
 
116
 
const QString & SwapTimer::family()
117
 
{
118
 
        return  m_family;
119
 
}
120
 
 
121
 
const QString & SwapTimer::prop()
122
 
{
123
 
        return m_prop;
124
 
}
125
 
 
126
 
QMap<QString, QString> SwapTimer::propsMap()
127
 
{
128
 
        return m_propsMap;
129
 
}
130
 
 
131
 
ItemBase * SwapTimer::itemBase()
132
 
{
133
 
        return m_itemBase;
134
 
}
135
 
 
136
 
///////////////////////////////////////////////
137
 
 
138
 
const QString MainWindow::UntitledSketchName = "Untitled Sketch";
139
 
int MainWindow::UntitledSketchIndex = 1;
140
 
int MainWindow::CascadeFactorX = 21;
141
 
int MainWindow::CascadeFactorY = 19;
142
 
int MainWindow::RestartNeeded = 0;
143
 
 
144
 
static const int MainWindowDefaultWidth = 840;
145
 
static const int MainWindowDefaultHeight = 600;
146
 
 
147
 
int MainWindow::AutosaveTimeoutMinutes = 10;   // in minutes
148
 
bool MainWindow::AutosaveEnabled = true;
149
 
QString MainWindow::BackupFolder;
150
 
 
151
 
/////////////////////////////////////////////
152
 
 
153
 
MainWindow::MainWindow(PaletteModel * paletteModel, ReferenceModel *refModel, QWidget * parent) :
154
 
    FritzingWindow(untitledFileName(), untitledFileCount(), fileExtension(), parent)
155
 
{
156
 
    setAcceptDrops(true);
157
 
        m_activeWire = NULL;
158
 
        m_activeConnectorItem = NULL;
159
 
        m_swapTimer.setInterval(30);
160
 
        m_swapTimer.setParent(this);
161
 
        m_swapTimer.setSingleShot(true);
162
 
        connect(&m_swapTimer, SIGNAL(timeout()), this, SLOT(swapSelectedTimeout()));
163
 
 
164
 
        m_closeSilently = false;
165
 
        m_orderFabAct = NULL;
166
 
        m_activeLayerButtonWidget = NULL;
167
 
        m_programWindow = NULL;
168
 
        m_windowMenuSeparator = NULL;
169
 
        m_wireColorMenu = NULL;
170
 
        m_viewSwitcherDock = NULL;
171
 
        m_checkForUpdatesAct = NULL;
172
 
        m_fileProgressDialog = NULL;
173
 
        m_currentGraphicsView = NULL;
174
 
        m_comboboxChanged = false;
175
 
        m_helper = NULL;
176
 
        m_smdOneSideWarningGiven = false;
177
 
 
178
 
    // Add a timer for autosaving
179
 
        m_backingUp = m_autosaveNeeded = false;
180
 
    connect(&m_autosaveTimer, SIGNAL(timeout()), this, SLOT(backupSketch()));
181
 
    m_autosaveTimer.start(AutosaveTimeoutMinutes * 60 * 1000);
182
 
 
183
 
        resize(MainWindowDefaultWidth, MainWindowDefaultHeight);
184
 
 
185
 
        m_backupFileNameAndPath = MainWindow::BackupFolder + "/" + FolderUtils::getRandText() + FritzingSketchExtension;
186
 
    // Connect the undoStack to our autosave stuff
187
 
    connect(m_undoStack, SIGNAL(indexChanged(int)), this, SLOT(autosaveNeeded(int)));
188
 
    connect(m_undoStack, SIGNAL(cleanChanged(bool)), this, SLOT(undoStackCleanChanged(bool)));
189
 
 
190
 
        // Create dot icons
191
 
        m_dotIcon = QIcon(":/resources/images/dot.png");
192
 
        m_emptyIcon = QIcon();
193
 
 
194
 
        m_currentWidget = NULL;
195
 
        m_firstOpen = true;
196
 
 
197
 
        m_statusBar = new QStatusBar(this);
198
 
        setStatusBar(m_statusBar);
199
 
        m_statusBar->setSizeGripEnabled(false);
200
 
 
201
 
        QSettings settings;
202
 
        m_locationLabelUnits = settings.value("LocationInches", "in").toString();
203
 
 
204
 
        // leave the m_orderFabEnabled check in case we turn off the fab button in the future
205
 
        m_orderFabEnabled = true; // settings.value(ORDERFABENABLED, QVariant(false)).toBool();
206
 
 
207
 
        m_locationLabel = new ClickableLabel("", this);
208
 
        m_locationLabel->setObjectName("LocationLabel");
209
 
        connect(m_locationLabel, SIGNAL(clicked()), this, SLOT(locationLabelClicked()));
210
 
        m_statusBar->addPermanentWidget(m_locationLabel);
211
 
 
212
 
        m_zoomSlider = new ZoomSlider(m_statusBar);
213
 
        connect(m_zoomSlider, SIGNAL(zoomChanged(double)), this, SLOT(updateViewZoom(double)));
214
 
        m_statusBar->addPermanentWidget(m_zoomSlider);
215
 
 
216
 
 
217
 
        setAttribute(Qt::WA_DeleteOnClose, true);
218
 
 
219
 
#ifdef Q_WS_MAC
220
 
        //setAttribute(Qt::WA_QuitOnClose, false);                                      // restoring this temporarily (2008.12.19)
221
 
#endif
222
 
    m_dontClose = m_closing = false;
223
 
 
224
 
        m_paletteModel = paletteModel;
225
 
        m_refModel = refModel;
226
 
        m_sketchModel = new SketchModel(true);
227
 
 
228
 
        m_tabWidget = new QStackedWidget(this); //   FTabWidget(this);
229
 
        m_tabWidget->setObjectName("sketch_tabs");
230
 
 
231
 
        setCentralWidget(m_tabWidget);
232
 
 
233
 
        QShortcut * shortcut = new QShortcut(QKeySequence(tr("Ctrl+R", "Rotate Clockwise")), this);
234
 
        connect(shortcut, SIGNAL(activated()), this, SLOT(rotateIncCW()));
235
 
        shortcut = new QShortcut(QKeySequence(tr("Alt+Ctrl+R", "Rotate Clockwise")), this);
236
 
        connect(shortcut, SIGNAL(activated()), this, SLOT(rotateIncCWRubberBand()));
237
 
        shortcut = new QShortcut(QKeySequence(tr("Meta+Ctrl+R", "Rotate Clockwise")), this);
238
 
        connect(shortcut, SIGNAL(activated()), this, SLOT(rotateIncCWRubberBand()));
239
 
 
240
 
        shortcut = new QShortcut(QKeySequence(tr("Shift+Ctrl+R", "Rotate Counterclockwise")), this);
241
 
        connect(shortcut, SIGNAL(activated()), this, SLOT(rotateIncCCW()));
242
 
        shortcut = new QShortcut(QKeySequence(tr("Alt+Shift+Ctrl+R", "Rotate Counterclockwise")), this);
243
 
        connect(shortcut, SIGNAL(activated()), this, SLOT(rotateIncCCWRubberBand()));
244
 
        shortcut = new QShortcut(QKeySequence(tr("Meta+Shift+Ctrl+R", "Rotate Counterclockwise")), this);
245
 
        connect(shortcut, SIGNAL(activated()), this, SLOT(rotateIncCCWRubberBand()));
246
 
 
247
 
        shortcut = new QShortcut(QKeySequence(tr("Shift+Ctrl+Tab", "Toggle Active Layer")), this);
248
 
        connect(shortcut, SIGNAL(activated()), this, SLOT(toggleActiveLayer()));
249
 
 
250
 
 
251
 
        connect(this, SIGNAL(changeActivationSignal(bool, QWidget *)), qApp, SLOT(changeActivation(bool, QWidget *)), Qt::DirectConnection);
252
 
        connect(this, SIGNAL(destroyed(QObject *)), qApp, SLOT(topLevelWidgetDestroyed(QObject *)));
253
 
        connect(this, SIGNAL(externalProcessSignal(QString &, QString &, QStringList &)),
254
 
                        qApp, SLOT(externalProcessSlot(QString &, QString &, QStringList &)), 
255
 
                        Qt::DirectConnection);
256
 
}
257
 
 
258
 
void MainWindow::init(PaletteModel * paletteModel, ReferenceModel *refModel, bool lockFiles) {
259
 
    m_paletteModel = paletteModel;
260
 
    m_refModel = refModel;
261
 
    m_restarting = false;
262
 
 
263
 
        if (m_fileProgressDialog) {
264
 
                m_fileProgressDialog->setValue(2);
265
 
        }
266
 
 
267
 
        LockManager::initLockedFiles("fzz", m_fzzFolder, m_fzzFiles, lockFiles ? LockManager::SlowTime : 0);
268
 
        if (lockFiles) {
269
 
                QFileInfoList backupList;
270
 
                LockManager::checkLockedFiles("fzz", backupList, m_fzzFiles, true, LockManager::SlowTime);
271
 
        }
272
 
 
273
 
        DebugDialog::debug("init sketch widgets");
274
 
 
275
 
        // all this belongs in viewLayer.xml
276
 
        m_breadboardGraphicsView = new BreadboardSketchWidget(ViewIdentifierClass::BreadboardView, this);
277
 
        initSketchWidget(m_breadboardGraphicsView);
278
 
        m_breadboardWidget = new SketchAreaWidget(m_breadboardGraphicsView,this);
279
 
        m_tabWidget->addWidget(m_breadboardWidget);
280
 
 
281
 
        if (m_fileProgressDialog) {
282
 
                m_fileProgressDialog->setValue(11);
283
 
        }
284
 
 
285
 
 
286
 
        m_schematicGraphicsView = new SchematicSketchWidget(ViewIdentifierClass::SchematicView, this);
287
 
        initSketchWidget(m_schematicGraphicsView);
288
 
        m_schematicWidget = new SketchAreaWidget(m_schematicGraphicsView, this);
289
 
        m_tabWidget->addWidget(m_schematicWidget);
290
 
 
291
 
        if (m_fileProgressDialog) {
292
 
                m_fileProgressDialog->setValue(20);
293
 
        }
294
 
 
295
 
        m_pcbGraphicsView = new PCBSketchWidget(ViewIdentifierClass::PCBView, this);
296
 
        initSketchWidget(m_pcbGraphicsView);
297
 
        m_pcbWidget = new SketchAreaWidget(m_pcbGraphicsView, this);
298
 
        m_tabWidget->addWidget(m_pcbWidget);
299
 
 
300
 
        if (m_fileProgressDialog) {
301
 
                m_fileProgressDialog->setValue(29);
302
 
        }
303
 
 
304
 
    m_undoView = new QUndoView();
305
 
    m_undoGroup = new QUndoGroup(this);
306
 
    m_undoView->setGroup(m_undoGroup);
307
 
    m_undoGroup->setActiveStack(m_undoStack);
308
 
 
309
 
        m_layerPalette = new LayerPalette(this);
310
 
 
311
 
        DebugDialog::debug("before creating dock");
312
 
 
313
 
    m_dockManager = new DockManager(this);
314
 
        DebugDialog::debug("before creating bins");
315
 
 
316
 
        m_dockManager->createBinAndInfoViewDocks();
317
 
 
318
 
        DebugDialog::debug("after creating bins");
319
 
        if (m_fileProgressDialog) {
320
 
                m_fileProgressDialog->setValue(89);
321
 
        }
322
 
 
323
 
 
324
 
 
325
 
        // This is the magic translation that changes all the shortcut text on the menu items
326
 
        // to the native language instead of "Ctrl", so the German menu items will now read "Strg"
327
 
        // You don't actually have to translate every menu item in the .ts file, you can just leave it as "Ctrl".
328
 
        QShortcut::tr("Ctrl", "for naming shortcut keys on menu items");
329
 
        QShortcut::tr("Alt", "for naming shortcut keys on menu items");
330
 
        QShortcut::tr("Shift", "for naming shortcut keys on menu items");
331
 
        QShortcut::tr("Meta", "for naming shortcut keys on menu items");
332
 
 
333
 
        DebugDialog::debug("create menus");
334
 
 
335
 
    createActions();
336
 
    createMenus();
337
 
 
338
 
        DebugDialog::debug("create toolbars");
339
 
 
340
 
    createToolBars();
341
 
    createStatusBar();
342
 
 
343
 
        DebugDialog::debug("after creating status bar");
344
 
 
345
 
        if (m_fileProgressDialog) {
346
 
                m_fileProgressDialog->setValue(91);
347
 
        }
348
 
 
349
 
        DebugDialog::debug("create view switcher");
350
 
 
351
 
        m_layerPalette->setShowAllLayersAction(m_showAllLayersAct);
352
 
        m_layerPalette->setHideAllLayersAction(m_hideAllLayersAct);
353
 
 
354
 
        m_viewSwitcher = new ViewSwitcher();
355
 
        connect(m_viewSwitcher, SIGNAL(viewSwitched(int)), this, SLOT(viewSwitchedTo(int)));
356
 
        connect(this, SIGNAL(viewSwitched(int)), m_viewSwitcher, SLOT(viewSwitchedTo(int)));
357
 
        m_viewSwitcher->viewSwitchedTo(0);
358
 
 
359
 
    m_dockManager->createDockWindows();
360
 
 
361
 
        if (m_fileProgressDialog) {
362
 
                m_fileProgressDialog->setValue(93);
363
 
        }
364
 
 
365
 
        createZoomOptions(m_breadboardWidget);
366
 
        createZoomOptions(m_schematicWidget);
367
 
        createZoomOptions(m_pcbWidget);
368
 
 
369
 
    m_breadboardWidget->setToolbarWidgets(getButtonsForView(m_breadboardWidget->viewIdentifier()));
370
 
    m_schematicWidget->setToolbarWidgets(getButtonsForView(m_schematicWidget->viewIdentifier()));
371
 
        m_pcbWidget->setToolbarWidgets(getButtonsForView(m_pcbWidget->viewIdentifier()));
372
 
 
373
 
        QFile styleSheet(":/resources/styles/fritzing.qss");
374
 
    if (!styleSheet.open(QIODevice::ReadOnly)) {
375
 
                qWarning("Unable to open :/resources/styles/fritzing.qss");
376
 
        } else {
377
 
                QString platformDependantStyle = "";
378
 
                QString platformDependantStylePath;
379
 
#ifdef Q_WS_X11
380
 
                if(style()->metaObject()->className()==QString("OxygenStyle")) {
381
 
                        QFile oxygenStyleSheet(":/resources/styles/linux-kde-oxygen.qss");
382
 
                        if(oxygenStyleSheet.open(QIODevice::ReadOnly)) {
383
 
                                platformDependantStyle += oxygenStyleSheet.readAll();
384
 
                        }
385
 
                }
386
 
                platformDependantStylePath = ":/resources/styles/linux.qss";
387
 
#endif
388
 
 
389
 
#ifdef Q_WS_MAC
390
 
                platformDependantStylePath = ":/resources/styles/mac.qss";
391
 
#endif
392
 
 
393
 
#ifdef Q_WS_WIN
394
 
                platformDependantStylePath = ":/resources/styles/win.qss";
395
 
#endif
396
 
 
397
 
                QFile platformDependantStyleSheet(platformDependantStylePath);
398
 
                if(platformDependantStyleSheet.open(QIODevice::ReadOnly)) {
399
 
                        platformDependantStyle += platformDependantStyleSheet.readAll();
400
 
                }
401
 
                setStyleSheet(styleSheet.readAll()+platformDependantStyle);
402
 
        }
403
 
 
404
 
    m_breadboardGraphicsView->setItemMenu(breadboardItemMenu());
405
 
    m_breadboardGraphicsView->setWireMenu(breadboardWireMenu());
406
 
 
407
 
    m_pcbGraphicsView->setWireMenu(pcbWireMenu());
408
 
    m_pcbGraphicsView->setItemMenu(pcbItemMenu());
409
 
 
410
 
    m_schematicGraphicsView->setItemMenu(schematicItemMenu());
411
 
    m_schematicGraphicsView->setWireMenu(schematicWireMenu());
412
 
 
413
 
    m_breadboardGraphicsView->setInfoView(m_infoView);
414
 
    m_pcbGraphicsView->setInfoView(m_infoView);
415
 
    m_schematicGraphicsView->setInfoView(m_infoView);
416
 
 
417
 
        // make sure to set the connections after the views have been created
418
 
        connect(m_tabWidget, SIGNAL(currentChanged ( int )), this, SLOT(tabWidget_currentChanged( int )));
419
 
 
420
 
        connectPairs();
421
 
 
422
 
        m_helper = new Helper(this, true);
423
 
 
424
 
        // do this the first time, since the current_changed signal wasn't sent
425
 
        int tab = 0;
426
 
        currentNavigatorChanged(m_navigators[tab]);
427
 
        tabWidget_currentChanged(tab+1);
428
 
        tabWidget_currentChanged(tab);
429
 
 
430
 
        this->installEventFilter(this);
431
 
 
432
 
        if (m_fileProgressDialog) {
433
 
                m_fileProgressDialog->setValue(95);
434
 
        }
435
 
 
436
 
        QSettings settings;
437
 
    m_viewSwitcherDock->prestorePreference();
438
 
        if(!settings.value("main/state").isNull()) {
439
 
                restoreState(settings.value("main/state").toByteArray());
440
 
                restoreGeometry(settings.value("main/geometry").toByteArray());
441
 
        }
442
 
    m_viewSwitcherDock->restorePreference();
443
 
    m_viewSwitcherDock->setViewSwitcher(m_viewSwitcher);
444
 
 
445
 
        setMinimumSize(0,0);
446
 
        m_tabWidget->setMinimumWidth(500);
447
 
        m_tabWidget->setMinimumWidth(0);
448
 
 
449
 
        m_miniViewContainerBreadboard->setView(m_breadboardGraphicsView);
450
 
        m_miniViewContainerSchematic->setView(m_schematicGraphicsView);
451
 
        m_miniViewContainerPCB->setView(m_pcbGraphicsView);
452
 
 
453
 
        connect(this, SIGNAL(readOnlyChanged(bool)), this, SLOT(applyReadOnlyChange(bool)));
454
 
 
455
 
        m_setUpDockManagerTimer.setSingleShot(true);
456
 
        connect(&m_setUpDockManagerTimer, SIGNAL(timeout()), m_dockManager, SLOT(keepMargins()));
457
 
    m_setUpDockManagerTimer.start(1000);
458
 
 
459
 
        if (m_fileProgressDialog) {
460
 
                m_fileProgressDialog->setValue(98);
461
 
        }
462
 
 
463
 
}
464
 
 
465
 
MainWindow::~MainWindow()
466
 
{
467
 
    // Delete backup of this sketch if one exists.
468
 
    QFile::remove(m_backupFileNameAndPath);     
469
 
        
470
 
        delete m_sketchModel;
471
 
        m_dockManager->dontKeepMargins();
472
 
        m_setUpDockManagerTimer.stop();
473
 
 
474
 
        foreach (LinkedFile * linkedFile, m_linkedProgramFiles) {
475
 
                delete linkedFile;
476
 
        }
477
 
        m_linkedProgramFiles.clear();
478
 
 
479
 
        if (!m_fzzFolder.isEmpty()) {
480
 
                LockManager::releaseLockedFiles(m_fzzFolder, m_fzzFiles);
481
 
                FolderUtils::rmdir(m_fzzFolder);
482
 
        }
483
 
}                                          
484
 
 
485
 
void MainWindow::showNavigator() {
486
 
        m_navigatorDock->setFloating(false);
487
 
}
488
 
 
489
 
void MainWindow::initSketchWidget(SketchWidget * sketchWidget) {
490
 
        sketchWidget->setPaletteModel(m_paletteModel);
491
 
        sketchWidget->setSketchModel(m_sketchModel);
492
 
        sketchWidget->setRefModel(m_refModel);
493
 
        sketchWidget->setUndoStack(m_undoStack);
494
 
        sketchWidget->setChainDrag(true);                       // enable bend points
495
 
        sketchWidget->initGrid();
496
 
        sketchWidget->addViewLayers();
497
 
}
498
 
 
499
 
void MainWindow::connectPairs() {
500
 
        connectPair(m_breadboardGraphicsView, m_schematicGraphicsView);
501
 
        connectPair(m_breadboardGraphicsView, m_pcbGraphicsView);
502
 
        connectPair(m_schematicGraphicsView, m_breadboardGraphicsView);
503
 
        connectPair(m_schematicGraphicsView, m_pcbGraphicsView);
504
 
        connectPair(m_pcbGraphicsView, m_breadboardGraphicsView);
505
 
        connectPair(m_pcbGraphicsView, m_schematicGraphicsView);
506
 
 
507
 
        connect(m_pcbGraphicsView, SIGNAL(groundFillSignal()), this, SLOT(groundFill()));
508
 
        connect(m_pcbGraphicsView, SIGNAL(copperFillSignal()), this, SLOT(copperFill()));
509
 
 
510
 
    connect(m_pcbGraphicsView, SIGNAL(swapBoardImageSignal(SketchWidget *, ItemBase *, const QString &, const QString &, bool)),
511
 
                this, SLOT(swapBoardImageSlot(SketchWidget *, ItemBase *, const QString &, const QString &, bool)));
512
 
 
513
 
 
514
 
        connect(m_breadboardGraphicsView, SIGNAL(setActiveWireSignal(Wire *)), this, SLOT(setActiveWire(Wire *)));
515
 
        connect(m_schematicGraphicsView, SIGNAL(setActiveWireSignal(Wire *)), this, SLOT(setActiveWire(Wire *)));
516
 
        connect(m_pcbGraphicsView, SIGNAL(setActiveWireSignal(Wire *)), this, SLOT(setActiveWire(Wire *)));
517
 
 
518
 
        connect(m_breadboardGraphicsView, SIGNAL(setActiveConnectorItemSignal(ConnectorItem *)), this, SLOT(setActiveConnectorItem(ConnectorItem *)));
519
 
        connect(m_schematicGraphicsView, SIGNAL(setActiveConnectorItemSignal(ConnectorItem *)), this, SLOT(setActiveConnectorItem(ConnectorItem *)));
520
 
        connect(m_pcbGraphicsView, SIGNAL(setActiveConnectorItemSignal(ConnectorItem *)), this, SLOT(setActiveConnectorItem(ConnectorItem *)));
521
 
 
522
 
        bool succeeded = connect(m_pcbGraphicsView, SIGNAL(routingStatusSignal(SketchWidget *, const RoutingStatus &)),
523
 
                                                this, SLOT(routingStatusSlot(SketchWidget *, const RoutingStatus &)));
524
 
        succeeded =  succeeded && connect(m_schematicGraphicsView, SIGNAL(routingStatusSignal(SketchWidget *, const RoutingStatus &)),
525
 
                                                this, SLOT(routingStatusSlot(SketchWidget *, const RoutingStatus &)));
526
 
        succeeded =  succeeded && connect(m_breadboardGraphicsView, SIGNAL(routingStatusSignal(SketchWidget *, const RoutingStatus &)),
527
 
                                                this, SLOT(routingStatusSlot(SketchWidget *, const RoutingStatus &)));
528
 
 
529
 
        succeeded =  succeeded && connect(m_breadboardGraphicsView, SIGNAL(swapSignal(const QString &, const QString &, QMap<QString, QString> &, ItemBase *)), 
530
 
                                                this, SLOT(swapSelectedDelay(const QString &, const QString &, QMap<QString, QString> &, ItemBase *)));
531
 
        succeeded =  succeeded && connect(m_schematicGraphicsView, SIGNAL(swapSignal(const QString &, const QString &, QMap<QString, QString> &, ItemBase *)), 
532
 
                                                this, SLOT(swapSelectedDelay(const QString &, const QString &, QMap<QString, QString> &, ItemBase *)));
533
 
        succeeded =  succeeded && connect(m_pcbGraphicsView, SIGNAL(swapSignal(const QString &, const QString &, QMap<QString, QString> &, ItemBase *)), 
534
 
                                                this, SLOT(swapSelectedDelay(const QString &, const QString &, QMap<QString, QString> &, ItemBase *)));
535
 
 
536
 
        succeeded =  succeeded && connect(m_breadboardGraphicsView, SIGNAL(warnSMDSignal(const QString &)), this, SLOT(warnSMD(const QString &)), Qt::QueuedConnection);
537
 
        succeeded =  succeeded && connect(m_pcbGraphicsView, SIGNAL(warnSMDSignal(const QString &)), this, SLOT(warnSMD(const QString &)), Qt::QueuedConnection);
538
 
        succeeded =  succeeded && connect(m_schematicGraphicsView, SIGNAL(warnSMDSignal(const QString &)), this, SLOT(warnSMD(const QString &)), Qt::QueuedConnection);
539
 
 
540
 
 
541
 
        succeeded =  succeeded && connect(m_breadboardGraphicsView, SIGNAL(dropPasteSignal(SketchWidget *)), 
542
 
                                                this, SLOT(dropPaste(SketchWidget *)));
543
 
        succeeded =  succeeded && connect(m_schematicGraphicsView, SIGNAL(dropPasteSignal(SketchWidget *)), 
544
 
                                                this, SLOT(dropPaste(SketchWidget *)));
545
 
        succeeded =  succeeded && connect(m_pcbGraphicsView, SIGNAL(dropPasteSignal(SketchWidget *)), 
546
 
                                                this, SLOT(dropPaste(SketchWidget *)));
547
 
        
548
 
        succeeded =  succeeded && connect(m_pcbGraphicsView, SIGNAL(subSwapSignal(SketchWidget *, ItemBase *, const QString &, ViewLayer::ViewLayerSpec, long &, QUndoCommand *)),
549
 
                                                this, SLOT(subSwapSlot(SketchWidget *, ItemBase *, const QString &, ViewLayer::ViewLayerSpec, long &, QUndoCommand *)),
550
 
                                                Qt::DirectConnection);
551
 
 
552
 
        succeeded =  succeeded && connect(m_pcbGraphicsView, SIGNAL(firstTimeHelpHidden()), this, SLOT(firstTimeHelpHidden()));
553
 
        succeeded =  succeeded && connect(m_schematicGraphicsView, SIGNAL(firstTimeHelpHidden()), this, SLOT(firstTimeHelpHidden()));
554
 
        succeeded =  succeeded && connect(m_breadboardGraphicsView, SIGNAL(firstTimeHelpHidden()), this, SLOT(firstTimeHelpHidden()));
555
 
 
556
 
        succeeded =  succeeded && connect(m_pcbGraphicsView, SIGNAL(updateLayerMenuSignal()), this, SLOT(updateLayerMenuSlot()));
557
 
        succeeded =  succeeded && connect(m_pcbGraphicsView, SIGNAL(changeBoardLayersSignal(int, bool )), this, SLOT(changeBoardLayers(int, bool )));
558
 
 
559
 
 
560
 
        succeeded =  succeeded && connect(qApp, SIGNAL(spaceBarIsPressedSignal(bool)), m_breadboardGraphicsView, SLOT(spaceBarIsPressedSlot(bool)));
561
 
        succeeded =  succeeded && connect(qApp, SIGNAL(spaceBarIsPressedSignal(bool)), m_schematicGraphicsView, SLOT(spaceBarIsPressedSlot(bool)));
562
 
        succeeded =  succeeded && connect(qApp, SIGNAL(spaceBarIsPressedSignal(bool)), m_pcbGraphicsView, SLOT(spaceBarIsPressedSlot(bool)));
563
 
 
564
 
        succeeded =  succeeded && connect(m_pcbGraphicsView, SIGNAL(boardDeletedSignal()), this, SLOT(boardDeletedSlot()));
565
 
 
566
 
        succeeded =  succeeded && connect(m_pcbGraphicsView, SIGNAL(cursorLocationSignal(double, double)), this, SLOT(cursorLocationSlot(double, double)));
567
 
        succeeded =  succeeded && connect(m_breadboardGraphicsView, SIGNAL(cursorLocationSignal(double, double)), this, SLOT(cursorLocationSlot(double, double)));
568
 
        succeeded =  succeeded && connect(m_schematicGraphicsView, SIGNAL(cursorLocationSignal(double, double)), this, SLOT(cursorLocationSlot(double, double)));
569
 
 
570
 
        succeeded =  succeeded && connect(m_breadboardGraphicsView, SIGNAL(filenameIfSignal(QString &)), this, SLOT(filenameIfSlot(QString &)), Qt::DirectConnection);
571
 
        succeeded =  succeeded && connect(m_pcbGraphicsView, SIGNAL(filenameIfSignal(QString &)), this, SLOT(filenameIfSlot(QString &)), Qt::DirectConnection);
572
 
        succeeded =  succeeded && connect(m_schematicGraphicsView, SIGNAL(filenameIfSignal(QString &)), this, SLOT(filenameIfSlot(QString &)), Qt::DirectConnection);
573
 
        
574
 
    if (!succeeded) {
575
 
                DebugDialog::debug("connectPair failed");
576
 
        }
577
 
}
578
 
 
579
 
void MainWindow::connectPair(SketchWidget * signaller, SketchWidget * slotter)
580
 
{
581
 
 
582
 
        bool succeeded = connect(signaller, SIGNAL(itemAddedSignal(ModelPart *, ViewLayer::ViewLayerSpec, const ViewGeometry &, long, SketchWidget *)),
583
 
                                                         slotter, SLOT(itemAddedSlot(ModelPart *, ViewLayer::ViewLayerSpec, const ViewGeometry &, long, SketchWidget *)));
584
 
 
585
 
        succeeded = succeeded && connect(signaller, SIGNAL(itemDeletedSignal(long)),
586
 
                                                                         slotter, SLOT(itemDeletedSlot(long)),
587
 
                                                                         Qt::DirectConnection);
588
 
 
589
 
        succeeded = succeeded && connect(signaller, SIGNAL(clearSelectionSignal()),
590
 
                                                                         slotter, SLOT(clearSelectionSlot()));
591
 
 
592
 
        succeeded = succeeded && connect(signaller, SIGNAL(itemSelectedSignal(long, bool)),
593
 
                                                                         slotter, SLOT(itemSelectedSlot(long, bool)));
594
 
        succeeded = succeeded && connect(signaller, SIGNAL(selectAllItemsSignal(bool, bool)),
595
 
                                                                         slotter, SLOT(selectAllItems(bool, bool)));
596
 
        succeeded = succeeded && connect(signaller, SIGNAL(wireDisconnectedSignal(long, QString)),
597
 
                                                                         slotter, SLOT(wireDisconnectedSlot(long,  QString)));
598
 
        succeeded = succeeded && connect(signaller, SIGNAL(wireConnectedSignal(long,  QString, long,  QString)),
599
 
                                                                         slotter, SLOT(wireConnectedSlot(long, QString, long, QString)));
600
 
        succeeded = succeeded && connect(signaller, SIGNAL(changeConnectionSignal(long,  QString, long,  QString, ViewLayer::ViewLayerSpec, bool, bool)),
601
 
                                                                         slotter, SLOT(changeConnectionSlot(long, QString, long, QString, ViewLayer::ViewLayerSpec, bool, bool)));
602
 
        succeeded = succeeded && connect(signaller, SIGNAL(copyBoundingRectsSignal(QHash<QString, QRectF> &)),
603
 
                                                                                                           slotter, SLOT(copyBoundingRectsSlot(QHash<QString, QRectF> &)),
604
 
                                                                         Qt::DirectConnection);
605
 
 
606
 
        succeeded = succeeded && connect(signaller, SIGNAL(cleanUpWiresSignal(CleanUpWiresCommand *)),
607
 
                                                                         slotter, SLOT(cleanUpWiresSlot(CleanUpWiresCommand *)) );
608
 
 
609
 
        succeeded = succeeded && connect(signaller, SIGNAL(checkStickySignal(long, bool, bool, CheckStickyCommand *)),
610
 
                                                                         slotter, SLOT(checkSticky(long, bool, bool, CheckStickyCommand *)) );
611
 
 
612
 
        succeeded = succeeded && connect(signaller, SIGNAL(disconnectAllSignal(QList<ConnectorItem *>, QHash<ItemBase *, SketchWidget *> &, QUndoCommand *)),
613
 
                                                                         slotter, SLOT(disconnectAllSlot(QList<ConnectorItem *>, QHash<ItemBase *, SketchWidget *> &, QUndoCommand *)),
614
 
                                                                         Qt::DirectConnection);
615
 
        succeeded = succeeded && connect(signaller, SIGNAL(setResistanceSignal(long, QString, QString, bool)),
616
 
                                                                         slotter, SLOT(setResistance(long, QString, QString, bool)));
617
 
        succeeded = succeeded && connect(signaller, SIGNAL(makeDeleteItemCommandPrepSignal(ItemBase *, bool , QUndoCommand * )),
618
 
                                                                         slotter, SLOT(makeDeleteItemCommandPrepSlot(ItemBase * , bool , QUndoCommand * )));
619
 
        succeeded = succeeded && connect(signaller, SIGNAL(makeDeleteItemCommandFinalSignal(ItemBase *, bool , QUndoCommand * )),
620
 
                                                                         slotter, SLOT(makeDeleteItemCommandFinalSlot(ItemBase * , bool , QUndoCommand * )));
621
 
 
622
 
        succeeded = succeeded && connect(signaller, SIGNAL(setPropSignal(long,  const QString &,  const QString &, bool, bool)),
623
 
                                                                         slotter, SLOT(setProp(long,  const QString &,  const QString &, bool, bool)));
624
 
 
625
 
        succeeded = succeeded && connect(signaller, SIGNAL(setInstanceTitleSignal(long, const QString &, const QString &, bool, bool )),
626
 
                                                                         slotter, SLOT(setInstanceTitle(long, const QString &, const QString &, bool, bool )));
627
 
 
628
 
        succeeded = succeeded && connect(signaller, SIGNAL(setVoltageSignal(double, bool )),
629
 
                                                                         slotter, SLOT(setVoltage(double, bool )));
630
 
 
631
 
        succeeded = succeeded && connect(signaller, SIGNAL(showLabelFirstTimeSignal(long, bool, bool )),
632
 
                                                                         slotter, SLOT(showLabelFirstTime(long, bool, bool )));
633
 
 
634
 
        succeeded = succeeded && connect(signaller, SIGNAL(changeBoardLayersSignal(int, bool )),
635
 
                                                                         slotter, SLOT(changeBoardLayers(int, bool )));
636
 
 
637
 
        succeeded = succeeded && connect(signaller, SIGNAL(deleteTracesSignal(QSet<ItemBase *> &, QHash<ItemBase *, SketchWidget *> &, QList<long> &, bool, QUndoCommand *)),
638
 
                                                                         slotter, SLOT(deleteTracesSlot(QSet<ItemBase *> &, QHash<ItemBase *, SketchWidget *> &, QList<long> &, bool, QUndoCommand *)),
639
 
                                                                         Qt::DirectConnection);
640
 
 
641
 
        succeeded = succeeded && connect(signaller, SIGNAL(ratsnestConnectSignal(long, const QString &, bool, bool)),
642
 
                                                                         slotter, SLOT(ratsnestConnect(long, const QString &, bool, bool )),
643
 
                                                                         Qt::DirectConnection);
644
 
 
645
 
 
646
 
        succeeded = succeeded && connect(signaller, SIGNAL(updatePartLabelInstanceTitleSignal(long)),
647
 
                                                                         slotter, SLOT(updatePartLabelInstanceTitleSlot(long)));
648
 
 
649
 
        succeeded = succeeded && connect(signaller, SIGNAL(changePinLabelsSignal(ItemBase *, bool)),
650
 
                                                                         slotter, SLOT(changePinLabelsSlot(ItemBase *, bool)));
651
 
 
652
 
        succeeded = succeeded && connect(signaller, SIGNAL(collectRatsnestSignal(QList<SketchWidget *> &)),
653
 
                                                                         slotter, SLOT(collectRatsnestSlot(QList<SketchWidget *> &)),
654
 
                                                                         Qt::DirectConnection);
655
 
 
656
 
        succeeded = succeeded && connect(signaller, SIGNAL(removeRatsnestSignal(QList<struct ConnectorEdge *> &, QUndoCommand *)),
657
 
                                                                         slotter, SLOT(removeRatsnestSlot(QList<struct ConnectorEdge *> &, QUndoCommand *)),
658
 
                                                                         Qt::DirectConnection);
659
 
 
660
 
        succeeded = succeeded && connect(signaller, SIGNAL(canConnectSignal(Wire *, ItemBase *, bool &)),
661
 
                                                                         slotter, SLOT(canConnect(Wire *, ItemBase *, bool &)),
662
 
                                                                         Qt::DirectConnection);
663
 
 
664
 
        succeeded = succeeded && connect(signaller, SIGNAL(swapStartSignal(SwapThing &, bool)),
665
 
                                                                         slotter, SLOT(swapStart(SwapThing &, bool)),
666
 
                                                                         Qt::DirectConnection);
667
 
 
668
 
        if (!succeeded) {
669
 
                DebugDialog::debug("connectPair failed");
670
 
        }
671
 
 
672
 
}
673
 
 
674
 
void MainWindow::setCurrentFile(const QString &filename, bool addToRecent, bool setAsLastOpened) {
675
 
        setFileName(filename);
676
 
 
677
 
        if(setAsLastOpened) {
678
 
                QSettings settings;
679
 
                settings.setValue("lastOpenSketch",filename);
680
 
        }
681
 
 
682
 
        updateRaiseWindowAction();
683
 
        setTitle();
684
 
 
685
 
        if(addToRecent) {
686
 
                QSettings settings;
687
 
                QStringList files = settings.value("recentFileList").toStringList();
688
 
                files.removeAll(filename);
689
 
                files.prepend(filename);
690
 
                while (files.size() > MaxRecentFiles)
691
 
                        files.removeLast();
692
 
 
693
 
                settings.setValue("recentFileList", files);
694
 
        }
695
 
 
696
 
    foreach (QWidget *widget, QApplication::topLevelWidgets()) {
697
 
        MainWindow *mainWin = qobject_cast<MainWindow *>(widget);
698
 
        if (mainWin)
699
 
            mainWin->updateRecentFileActions();
700
 
    }
701
 
}
702
 
 
703
 
 
704
 
void MainWindow::createZoomOptions(SketchAreaWidget* parent) {
705
 
 
706
 
    connect(parent->graphicsView(), SIGNAL(zoomChanged(double)), this, SLOT(updateZoomSlider(double)));
707
 
    connect(parent->graphicsView(), SIGNAL(zoomOutOfRange(double)), this, SLOT(updateZoomOptionsNoMatterWhat(double)));
708
 
}
709
 
 
710
 
void MainWindow::createToolBars() {
711
 
        /* TODO: Mariano this is too hacky and requires some styling
712
 
         * around here and some else in the qss file
713
 
         */
714
 
        /*m_toolbar = new QToolBar(this);
715
 
        m_toolbar->setObjectName("fake_tabbar");
716
 
        m_toolbar->setFloatable(false);
717
 
        m_toolbar->setMovable(false);
718
 
        int height = 0; //  m_tabWidget->tabBar()->height();
719
 
        m_toolbar->layout()->setMargin(0);
720
 
        m_toolbar->setFixedHeight(height+10);
721
 
        m_toolbar->setMinimumWidth(400); // connect to tabwidget resize event
722
 
        m_toolbar->toggleViewAction()->setVisible(false);
723
 
        // m_tabWidget->tabBar()->setParent(m_toolbar);
724
 
        addToolBar(m_toolbar);*/
725
 
 
726
 
        /*      QToolBar *tb2 = new QToolBar(this);
727
 
        tb2->setFloatable(false);
728
 
        tb2->setMovable(false);
729
 
        QToolButton *dummyButton = new QToolButton();
730
 
        dummyButton->setIcon(QIcon(":/resources/images/toolbar_icons/toolbarExport_pdf_icon.png"));
731
 
        tb2->addWidget(dummyButton);
732
 
        QToolButton *dummyButton2 = new QToolButton();
733
 
        dummyButton2->setIcon(QIcon(":/resources/images/toolbar_icons/toolbarOrder_icon.png"));
734
 
        tb2->addWidget(dummyButton2);
735
 
        addToolBar(tb2);*/
736
 
 
737
 
        /*
738
 
    m_fileToolBar = addToolBar(tr("File"));
739
 
    m_fileToolBar->setObjectName("fileToolBar");
740
 
    m_fileToolBar->addAction(m_saveAct);
741
 
    m_fileToolBar->addAction(m_printAct);
742
 
 
743
 
    m_editToolBar = addToolBar(tr("Edit"));
744
 
    m_editToolBar->setObjectName("editToolBar");
745
 
    m_editToolBar->addAction(m_undoAct);
746
 
    m_editToolBar->addWidget(m_zoomOptsComboBox);
747
 
    */
748
 
}
749
 
 
750
 
ExpandingLabel * MainWindow::createRoutingStatusLabel(SketchAreaWidget * parent) {
751
 
        ExpandingLabel * routingStatusLabel = new ExpandingLabel(m_pcbWidget);
752
 
 
753
 
        connect(routingStatusLabel, SIGNAL(mousePressSignal(QMouseEvent*)), this, SLOT(routingStatusLabelMousePress(QMouseEvent*)));
754
 
        connect(routingStatusLabel, SIGNAL(mouseReleaseSignal(QMouseEvent*)), this, SLOT(routingStatusLabelMouseRelease(QMouseEvent*)));
755
 
 
756
 
        routingStatusLabel->setTextInteractionFlags(Qt::NoTextInteraction);
757
 
        routingStatusLabel->setCursor(Qt::ArrowCursor);
758
 
        routingStatusLabel->viewport()->setCursor(Qt::ArrowCursor);
759
 
 
760
 
        routingStatusLabel->setObjectName(SketchAreaWidget::RoutingStateLabelName);
761
 
        parent->setRoutingStatusLabel(routingStatusLabel);
762
 
        RoutingStatus routingStatus;
763
 
        routingStatus.zero();
764
 
        routingStatusSlot(parent->graphicsView(), routingStatus);
765
 
        return routingStatusLabel;
766
 
}
767
 
 
768
 
SketchToolButton *MainWindow::createRotateButton(SketchAreaWidget *parent) {
769
 
        QList<QAction*> rotateMenuActions;
770
 
        rotateMenuActions << m_rotate45ccwAct << m_rotate90ccwAct << m_rotate180Act << m_rotate90cwAct << m_rotate45cwAct;
771
 
        SketchToolButton * rotateButton = new SketchToolButton("Rotate",parent, rotateMenuActions);
772
 
        rotateButton->setDefaultAction(m_rotate90ccwAct);
773
 
        rotateButton->setText(tr("Rotate"));
774
 
 
775
 
        m_rotateButtons << rotateButton;
776
 
        return rotateButton;
777
 
}
778
 
 
779
 
SketchToolButton *MainWindow::createShareButton(SketchAreaWidget *parent) {
780
 
        SketchToolButton *shareButton = new SketchToolButton("Share",parent, m_shareOnlineAct);
781
 
        shareButton->setText(tr("Share"));
782
 
        shareButton->setEnabledIcon();                                  // seems to need this to display button icon first time
783
 
        return shareButton;
784
 
}
785
 
 
786
 
SketchToolButton *MainWindow::createFlipButton(SketchAreaWidget *parent) {
787
 
        QList<QAction*> flipMenuActions;
788
 
        flipMenuActions << m_flipHorizontalAct << m_flipVerticalAct;
789
 
        SketchToolButton *flipButton = new SketchToolButton("Flip",parent, flipMenuActions);
790
 
        flipButton->setText(tr("Flip"));
791
 
 
792
 
        m_flipButtons << flipButton;
793
 
        return flipButton;
794
 
}
795
 
 
796
 
SketchToolButton *MainWindow::createAutorouteButton(SketchAreaWidget *parent) {
797
 
        SketchToolButton *autorouteButton = new SketchToolButton("Autoroute",parent, m_autorouteAct);
798
 
        autorouteButton->setText(tr("Autoroute"));
799
 
 
800
 
        return autorouteButton;
801
 
}
802
 
 
803
 
SketchToolButton *MainWindow::createOrderFabButton(SketchAreaWidget *parent) {
804
 
        SketchToolButton *orderFabButton = new SketchToolButton("Order",parent, m_orderFabAct);
805
 
        orderFabButton->setText(tr("Order PCB"));
806
 
        orderFabButton->setEnabledIcon();                                       // seems to need this to display button icon first time
807
 
 
808
 
        return orderFabButton;
809
 
}
810
 
 
811
 
QWidget *MainWindow::createActiveLayerButton(SketchAreaWidget *parent) 
812
 
{
813
 
        QList<QAction *> actions;
814
 
        actions << m_activeLayerBothAct << m_activeLayerBottomAct << m_activeLayerTopAct;
815
 
 
816
 
        m_activeLayerButtonWidget = new QStackedWidget;
817
 
        m_activeLayerButtonWidget->setMaximumWidth(90);
818
 
 
819
 
        SketchToolButton * button = new SketchToolButton("ActiveLayer", parent, actions);
820
 
        button->setDefaultAction(m_activeLayerBottomAct);
821
 
        button->setText(tr("Both Layers"));
822
 
        m_activeLayerButtonWidget->addWidget(button);
823
 
 
824
 
        button = new SketchToolButton("ActiveLayerB", parent, actions);
825
 
        button->setDefaultAction(m_activeLayerTopAct);
826
 
        button->setText(tr("Bottom Layer"));
827
 
        m_activeLayerButtonWidget->addWidget(button);
828
 
 
829
 
        button = new SketchToolButton("ActiveLayerT", parent, actions);
830
 
        button->setDefaultAction(m_activeLayerBothAct);
831
 
        button->setText(tr("Top Layer"));
832
 
        m_activeLayerButtonWidget->addWidget(button);
833
 
 
834
 
        return m_activeLayerButtonWidget;
835
 
}
836
 
 
837
 
SketchToolButton *MainWindow::createNoteButton(SketchAreaWidget *parent) {
838
 
        SketchToolButton *noteButton = new SketchToolButton("Notes",parent, m_addNoteAct);
839
 
        noteButton->setText(tr("Add a note"));
840
 
        noteButton->setEnabledIcon();                                   // seems to need this to display button icon first time
841
 
        return noteButton;
842
 
}
843
 
 
844
 
SketchToolButton *MainWindow::createExportEtchableButton(SketchAreaWidget *parent) {
845
 
        QList<QAction*> actions;
846
 
        actions << m_exportEtchablePdfAct << m_exportEtchableSvgAct << m_exportGerberAct;
847
 
        SketchToolButton *exportEtchableButton = new SketchToolButton("Diy",parent, actions);
848
 
        exportEtchableButton->setDefaultAction(m_exportEtchablePdfAct);
849
 
        exportEtchableButton->setText(tr("Export for PCB"));
850
 
        exportEtchableButton->setEnabledIcon();                         // seems to need this to display button icon first time
851
 
        return exportEtchableButton;
852
 
}
853
 
 
854
 
QWidget *MainWindow::createToolbarSpacer(SketchAreaWidget *parent) {
855
 
        QFrame *toolbarSpacer = new QFrame(parent);
856
 
        QHBoxLayout *spacerLayout = new QHBoxLayout(toolbarSpacer);
857
 
        spacerLayout->addSpacerItem(new QSpacerItem(0,0,QSizePolicy::Expanding));
858
 
 
859
 
        return toolbarSpacer;
860
 
}
861
 
 
862
 
QList<QWidget*> MainWindow::getButtonsForView(ViewIdentifierClass::ViewIdentifier viewId) {
863
 
        QList<QWidget*> retval;
864
 
        SketchAreaWidget *parent;
865
 
        switch(viewId) {
866
 
                case ViewIdentifierClass::BreadboardView: parent = m_breadboardWidget; break;
867
 
                case ViewIdentifierClass::SchematicView: parent = m_schematicWidget; break;
868
 
                case ViewIdentifierClass::PCBView: parent = m_pcbWidget; break;
869
 
                default: return retval;
870
 
        }
871
 
        retval << createShareButton(parent);
872
 
 
873
 
        switch(viewId) {
874
 
                case ViewIdentifierClass::BreadboardView:
875
 
                case ViewIdentifierClass::SchematicView:
876
 
                        retval << createNoteButton(parent);
877
 
                default: 
878
 
                        break;
879
 
        }
880
 
        
881
 
        retval << createRotateButton(parent);
882
 
        switch (viewId) {
883
 
                case ViewIdentifierClass::BreadboardView:
884
 
                        retval << createFlipButton(parent); 
885
 
                        break;
886
 
                case ViewIdentifierClass::SchematicView:
887
 
                        retval << createFlipButton(parent) << createToolbarSpacer(parent) << createAutorouteButton(parent);
888
 
                        break;
889
 
                case ViewIdentifierClass::PCBView:
890
 
                        retval << SketchAreaWidget::separator(parent) 
891
 
                                << createActiveLayerButton(parent) 
892
 
                                << createAutorouteButton(parent) 
893
 
                                << createExportEtchableButton(parent);
894
 
                        if (m_orderFabEnabled) {
895
 
                                retval << createOrderFabButton(parent);
896
 
                        }
897
 
                        break;
898
 
                default:
899
 
                        break;
900
 
        }
901
 
 
902
 
        retval << createRoutingStatusLabel(parent);
903
 
        return retval;
904
 
}
905
 
 
906
 
void MainWindow::updateZoomSlider(double zoom) {
907
 
        m_zoomSlider->setValue(zoom);
908
 
}
909
 
 
910
 
SketchAreaWidget *MainWindow::currentSketchArea() {
911
 
        return dynamic_cast<SketchAreaWidget*>(m_currentGraphicsView->parent());
912
 
}
913
 
 
914
 
void MainWindow::updateZoomOptionsNoMatterWhat(double zoom) {
915
 
        m_zoomSlider->setValue(zoom);
916
 
}
917
 
 
918
 
void MainWindow::updateViewZoom(double newZoom) {
919
 
        m_comboboxChanged = true;
920
 
        if(m_currentGraphicsView) m_currentGraphicsView->absoluteZoom(newZoom);
921
 
}
922
 
 
923
 
 
924
 
void MainWindow::createStatusBar()
925
 
{
926
 
    m_statusBar->showMessage(tr("Ready"));
927
 
}
928
 
 
929
 
void MainWindow::tabWidget_currentChanged(int index) {
930
 
        SketchAreaWidget * widgetParent = dynamic_cast<SketchAreaWidget *>(m_tabWidget->currentWidget());
931
 
        if (widgetParent == NULL) return;
932
 
 
933
 
        m_currentWidget = widgetParent;
934
 
 
935
 
        if (m_locationLabel) {
936
 
                m_locationLabel->setText("");
937
 
        }
938
 
 
939
 
        QStatusBar *sb = statusBar();
940
 
        connect(sb, SIGNAL(messageChanged(const QString &)), m_statusBar, SLOT(showMessage(const QString &)));
941
 
        widgetParent->addStatusBar(m_statusBar);
942
 
        if(sb != m_statusBar) sb->hide();
943
 
 
944
 
        if (m_breadboardGraphicsView) m_breadboardGraphicsView->setCurrent(false);
945
 
        if (m_schematicGraphicsView) m_schematicGraphicsView->setCurrent(false);
946
 
        if (m_pcbGraphicsView) m_pcbGraphicsView->setCurrent(false);
947
 
 
948
 
        SketchWidget *widget = widgetParent->graphicsView();
949
 
 
950
 
        if(m_currentGraphicsView) {
951
 
                m_currentGraphicsView->saveZoom(m_zoomSlider->value());
952
 
                disconnect(
953
 
                        m_currentGraphicsView,
954
 
                        SIGNAL(selectionChangedSignal()),
955
 
                        this,
956
 
                        SLOT(updateTransformationActions())
957
 
                );
958
 
        }
959
 
        m_currentGraphicsView = widget;
960
 
        if (widget == NULL) return;
961
 
 
962
 
        m_zoomSlider->setValue(m_currentGraphicsView->retrieveZoom());
963
 
 
964
 
        connect(
965
 
                m_currentGraphicsView,                                  // don't connect directly to the scene here, connect to the widget's signal
966
 
                SIGNAL(selectionChangedSignal()),
967
 
                this,
968
 
                SLOT(updateTransformationActions())
969
 
        );
970
 
 
971
 
        updateActiveLayerButtons();
972
 
 
973
 
        m_currentGraphicsView->setCurrent(true);
974
 
 
975
 
        // !!!!!! hack alert  !!!!!!!  
976
 
        // this item update loop seems to deal with a qt update bug:
977
 
        // if one view is visible and you change something in another view, 
978
 
        // the change might not appear when you switch views until you move the item in question
979
 
        foreach(QGraphicsItem * item, m_currentGraphicsView->items()) {
980
 
                item->update();
981
 
        }
982
 
 
983
 
        updateLayerMenu(true);
984
 
        QList<QAction *> actions;
985
 
        actions << m_showBreadboardAct << m_showSchematicAct << m_showPCBAct;
986
 
        setActionsIcons(index, actions);
987
 
 
988
 
        hideShowTraceMenu();
989
 
        updateTraceMenu();
990
 
        updateTransformationActions();
991
 
 
992
 
        setTitle();
993
 
 
994
 
        // triggers a signal to the navigator widget
995
 
        m_navigators[index]->miniViewMousePressedSlot();
996
 
        emit viewSwitched(index);
997
 
 
998
 
        if (m_helper == NULL) {
999
 
                m_showInViewHelpAct->setChecked(false);
1000
 
        }
1001
 
        else {
1002
 
                m_showInViewHelpAct->setChecked(m_helper->helpVisible(m_tabWidget->currentIndex()));
1003
 
        }
1004
 
 
1005
 
        m_currentGraphicsView->updateInfoView();
1006
 
 
1007
 
        // update issue with 4.5.1?: is this still valid (4.6.x?)
1008
 
        m_currentGraphicsView->updateConnectors();
1009
 
 
1010
 
}
1011
 
 
1012
 
void MainWindow::setActionsIcons(int index, QList<QAction *> & actions) {
1013
 
        for (int i = 0; i < actions.count(); i++) {
1014
 
                actions[i]->setIcon(index == i ? m_dotIcon : m_emptyIcon);
1015
 
        }
1016
 
}
1017
 
 
1018
 
void MainWindow::closeEvent(QCloseEvent *event) {
1019
 
        if (m_dontClose) {
1020
 
                event->ignore();
1021
 
                return;
1022
 
        }
1023
 
 
1024
 
        if (m_programWindow) {
1025
 
                m_programWindow->close();
1026
 
                if (m_programWindow->isVisible()) {
1027
 
                        event->ignore();
1028
 
                        return;
1029
 
                }
1030
 
        }
1031
 
 
1032
 
        if (!m_closeSilently) {
1033
 
                bool whatWithAliens = whatToDoWithAlienFiles();
1034
 
                if(!beforeClosing() || !whatWithAliens ||!m_binManager->beforeClosing()) {
1035
 
                        event->ignore();
1036
 
                        return;
1037
 
                }
1038
 
 
1039
 
                if(whatWithAliens && m_binManager->hasAlienParts()) {
1040
 
                        m_binManager->createIfMyPartsNotExists();
1041
 
                }
1042
 
        }
1043
 
 
1044
 
        DebugDialog::debug(QString("top level windows: %1").arg(QApplication::topLevelWidgets().size()));
1045
 
        /*
1046
 
        foreach (QWidget * widget, QApplication::topLevelWidgets()) {
1047
 
                QMenu * menu = qobject_cast<QMenu *>(widget);
1048
 
                if (menu != NULL) {
1049
 
                        continue;                               // QMenus are always top level widgets, even if they have parents...
1050
 
                }
1051
 
                DebugDialog::debug(QString("top level widget %1 %2 %3")
1052
 
                        .arg(widget->metaObject()->className())
1053
 
                        .arg(widget->windowTitle())
1054
 
                        .arg(widget->toolTip())
1055
 
                        );
1056
 
        }
1057
 
        */
1058
 
 
1059
 
        m_closing = true;
1060
 
        emit aboutToClose();
1061
 
 
1062
 
        int count = 0;
1063
 
        foreach (QWidget *widget, QApplication::topLevelWidgets()) {
1064
 
                if (widget == this) continue;
1065
 
                if (qobject_cast<QMainWindow *>(widget) == NULL) continue;
1066
 
 
1067
 
                count++;
1068
 
        }
1069
 
 
1070
 
        if (count == 0) {
1071
 
                DebugDialog::closeDebug();
1072
 
        }
1073
 
 
1074
 
        QSettings settings;
1075
 
        settings.setValue("main/state",saveState());
1076
 
        settings.setValue("main/geometry",saveGeometry());
1077
 
 
1078
 
        QMainWindow::closeEvent(event);
1079
 
}
1080
 
 
1081
 
bool MainWindow::whatToDoWithAlienFiles() {
1082
 
        if (m_alienFiles.size() > 0) {
1083
 
                QMessageBox::StandardButton reply;
1084
 
                reply = QMessageBox::question(this, tr("Save %1").arg(QFileInfo(m_fwFilename).baseName()),
1085
 
                                                 m_alienPartsMsg
1086
 
                                                 .arg(QFileInfo(m_fwFilename).baseName()),
1087
 
                                                 QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel);
1088
 
                // TODO: translate button text
1089
 
                if (reply == QMessageBox::Yes) {
1090
 
                        return true;
1091
 
                } else if (reply == QMessageBox::No) {
1092
 
                        foreach(QString pathToRemove, m_alienFiles) {
1093
 
                                QFile::remove(pathToRemove);
1094
 
                        }
1095
 
                        m_alienFiles.clear();
1096
 
                        recoverBackupedFiles();
1097
 
 
1098
 
                        emit alienPartsDismissed();
1099
 
                        return true;
1100
 
                }
1101
 
                else {
1102
 
                        return false;
1103
 
                }
1104
 
        } else {
1105
 
                return true;
1106
 
        }
1107
 
}
1108
 
 
1109
 
void MainWindow::acceptAlienFiles() {
1110
 
        m_alienFiles.clear();
1111
 
}
1112
 
 
1113
 
void MainWindow::saveDocks()
1114
 
{
1115
 
        for (int i = 0; i < children().count(); i++) {
1116
 
                FDockWidget * dock = qobject_cast<FDockWidget *>(children()[i]);
1117
 
                if (dock == NULL) continue;
1118
 
 
1119
 
                //DebugDialog::debug(QString("saving dock %1").arg(dock->windowTitle()));
1120
 
                dock->saveState();
1121
 
 
1122
 
                if (dock->isFloating() && dock->isVisible()) {
1123
 
                        //DebugDialog::debug(QString("hiding dock %1").arg(dock->windowTitle()));
1124
 
                        dock->hide();
1125
 
                }
1126
 
        }
1127
 
}
1128
 
 
1129
 
void MainWindow::restoreDocks() {
1130
 
        for (int i = 0; i < children().count(); i++) {
1131
 
                FDockWidget * dock = qobject_cast<FDockWidget *>(children()[i]);
1132
 
                if (dock == NULL) continue;
1133
 
 
1134
 
                // DebugDialog::debug(QString("restoring dock %1").arg(dock->windowTitle()));
1135
 
                dock->restoreState();
1136
 
        }
1137
 
}
1138
 
 
1139
 
 
1140
 
ModelPart *MainWindow::loadPartFromFile(const QString& newPartPath, bool connectorsChanged) {
1141
 
        if(connectorsChanged && wannaRestart()) {
1142
 
                QApplication::exit(RestartNeeded);
1143
 
                return NULL;
1144
 
        } else {
1145
 
                ModelPart* mp = m_refModel->addPart(newPartPath, true, true);
1146
 
                m_refModel->addPart(mp,true);
1147
 
                return mp;
1148
 
        }
1149
 
}
1150
 
 
1151
 
bool MainWindow::wannaRestart() {
1152
 
        QMessageBox::StandardButton btn = QMessageBox::question(this,
1153
 
                tr("Updating existing part"),
1154
 
                tr("Some connectors have changed.\n"
1155
 
                        "In order to see the changes, you have to restart fritzing.\n"
1156
 
                        "Do you want to restart now?"
1157
 
                ),
1158
 
                QMessageBox::Yes|QMessageBox::No
1159
 
        );
1160
 
        bool result = (btn == QMessageBox::Yes);
1161
 
        if(result) {
1162
 
                m_restarting = true;
1163
 
                close();
1164
 
                m_restarting = false;
1165
 
        }
1166
 
        return result;
1167
 
}
1168
 
 
1169
 
void MainWindow::loadPart(const QString &newPartPath, long partsEditorId, bool connectorsChanged) {
1170
 
        ModelPart * modelPart = loadPartFromFile(newPartPath, connectorsChanged);
1171
 
        if(modelPart && modelPart->hasViewIdentifier(ViewIdentifierClass::IconView)) {
1172
 
                if(m_binsWithPartsEditorRequests.contains(partsEditorId)
1173
 
                   && !m_binsWithPartsEditorRequests[partsEditorId]->currentBinIsCore() ) {
1174
 
                        m_binManager->addPartTo(m_binsWithPartsEditorRequests[partsEditorId],modelPart, true);
1175
 
                } else {
1176
 
                        m_binManager->addNewPart(modelPart);
1177
 
                }
1178
 
                m_infoView->reloadContent(m_currentGraphicsView);
1179
 
        }
1180
 
}
1181
 
 
1182
 
bool MainWindow::eventFilter(QObject *object, QEvent *event) {
1183
 
        if (object == this &&
1184
 
                (event->type() == QEvent::KeyPress
1185
 
                // || event->type() == QEvent::KeyRelease
1186
 
                || event->type() == QEvent::ShortcutOverride))
1187
 
        {
1188
 
                //DebugDialog::debug(QString("event filter %1").arg(event->type()) );
1189
 
                updatePartMenu();
1190
 
                updateTraceMenu();
1191
 
 
1192
 
                // On the mac, the first time the delete key is pressed, to be used as a shortcut for QAction m_deleteAct,
1193
 
                // for some reason, the enabling of the m_deleteAct in UpdateEditMenu doesn't "take" until the next time the event loop is processed
1194
 
                // Thereafter, the delete key works as it should.
1195
 
                // So this call to processEvents() makes sure m_deleteAct is enabled.
1196
 
                ProcessEventBlocker::processEvents();
1197
 
        }
1198
 
 
1199
 
        return QMainWindow::eventFilter(object, event);
1200
 
}
1201
 
 
1202
 
const QString MainWindow::untitledFileName() {
1203
 
        return UntitledSketchName;
1204
 
}
1205
 
 
1206
 
int &MainWindow::untitledFileCount() {
1207
 
        return UntitledSketchIndex;
1208
 
}
1209
 
 
1210
 
const QString MainWindow::fileExtension() {
1211
 
        return FritzingBundleExtension;
1212
 
}
1213
 
 
1214
 
const QString MainWindow::defaultSaveFolder() {
1215
 
        return FolderUtils::openSaveFolder();
1216
 
}
1217
 
 
1218
 
bool MainWindow::undoStackIsEmpty() {
1219
 
        return m_undoStack->count() == 0;
1220
 
}
1221
 
 
1222
 
void MainWindow::setInfoViewOnHover(bool infoViewOnHover) {
1223
 
        m_breadboardGraphicsView->setInfoViewOnHover(infoViewOnHover);
1224
 
        m_schematicGraphicsView->setInfoViewOnHover(infoViewOnHover);
1225
 
        m_pcbGraphicsView->setInfoViewOnHover(infoViewOnHover);
1226
 
 
1227
 
        m_binManager->setInfoViewOnHover(infoViewOnHover);
1228
 
}
1229
 
 
1230
 
void MainWindow::loadBundledSketch(const QString &fileName, bool addToRecent, bool setAsLastOpened) {
1231
 
 
1232
 
        if(!FolderUtils::unzipTo(fileName, m_fzzFolder)) {
1233
 
                QMessageBox::warning(
1234
 
                        this,
1235
 
                        tr("Fritzing"),
1236
 
                        tr("Unable to open '%1'").arg(fileName)
1237
 
                );
1238
 
 
1239
 
                return;
1240
 
        }
1241
 
 
1242
 
        QDir dir(m_fzzFolder);
1243
 
    QString binFileName = dir.absoluteFilePath(QFileInfo(BinManager::TempPartsBinTemplateLocation).fileName());
1244
 
    m_binManager->setTempPartsBinLocation(binFileName);
1245
 
    FolderUtils::copyBin(binFileName, BinManager::TempPartsBinTemplateLocation);
1246
 
 
1247
 
        QStringList namefilters;
1248
 
        namefilters << "*"+FritzingSketchExtension;
1249
 
        QFileInfoList entryInfoList = dir.entryInfoList(namefilters);
1250
 
        if (entryInfoList.count() == 0) {
1251
 
                QMessageBox::warning(
1252
 
                        this,
1253
 
                        tr("Fritzing"),
1254
 
                        tr("No Sketch found in '%1'").arg(fileName)
1255
 
                );
1256
 
 
1257
 
                return;
1258
 
        }
1259
 
 
1260
 
        QFileInfo sketchInfo = entryInfoList[0];
1261
 
 
1262
 
        QString sketchName = dir.absoluteFilePath(sketchInfo.fileName());
1263
 
 
1264
 
    namefilters.clear();
1265
 
    namefilters << "*" + FritzingPartExtension;
1266
 
    entryInfoList = dir.entryInfoList(namefilters);
1267
 
    QRegExp moduleIDFinder("moduleId=\"([^\"]+)");
1268
 
 
1269
 
    namefilters.clear();
1270
 
        namefilters << "*.svg";
1271
 
        QFileInfoList svgEntryInfoList = dir.entryInfoList(namefilters);
1272
 
 
1273
 
    bool addedToTemp = false;
1274
 
 
1275
 
    foreach (QFileInfo fzpInfo, entryInfoList) {
1276
 
        QFile file(dir.absoluteFilePath(fzpInfo.fileName()));
1277
 
        if (!file.open(QFile::ReadOnly)) {
1278
 
            DebugDialog::debug(QString("unable to open %1: %2").arg(file.fileName()));
1279
 
            continue;
1280
 
        }
1281
 
 
1282
 
 
1283
 
        // TODO: could be more efficient by using a streamreader
1284
 
        QString fzp = file.readAll();
1285
 
        file.close();
1286
 
        int ix = fzp.indexOf(moduleIDFinder);
1287
 
        if (ix < 0) {
1288
 
            DebugDialog::debug(QString("unable to find module id in %1: %2").arg(file.fileName()).arg(fzp));
1289
 
            continue;
1290
 
        }
1291
 
 
1292
 
        QString moduleID = moduleIDFinder.cap(1);
1293
 
        ModelPart * mp = m_paletteModel->retrieveModelPart(moduleID);
1294
 
        if (mp == NULL) {
1295
 
            QDomDocument doc;
1296
 
            if (!doc.setContent(fzp)) {
1297
 
                DebugDialog::debug(QString("unable to parse fzp in %1: %2").arg(file.fileName()).arg(fzp));
1298
 
                continue;
1299
 
            }
1300
 
 
1301
 
 
1302
 
            mp = copyToPartsFolder(fzpInfo, false, false, PartFactory::folderPath(), "contrib");
1303
 
            if (mp == NULL) {
1304
 
                DebugDialog::debug(QString("unable to create model part in %1: %2").arg(file.fileName()).arg(fzp));
1305
 
                continue;
1306
 
            }
1307
 
 
1308
 
            QDomElement root = doc.documentElement();
1309
 
                QDomElement views = root.firstChildElement("views");
1310
 
                QDomElement view = views.firstChildElement();
1311
 
            while (!view.isNull()) {
1312
 
                QDomElement layers = view.firstChildElement("layers");
1313
 
                QString path = layers.attribute("image", "");
1314
 
                if (!path.isEmpty()) {
1315
 
                    int ix = path.indexOf("/");
1316
 
                    path = path.mid(ix + 1);
1317
 
                    for (int jx = svgEntryInfoList.count() - 1; jx >= 0; jx--) {
1318
 
                        QFileInfo svgInfo = svgEntryInfoList.at(jx);
1319
 
                        if (svgInfo.fileName().contains(path)) {
1320
 
                            copyToSvgFolder(svgInfo, false, PartFactory::folderPath(), "contrib");
1321
 
                            svgEntryInfoList.removeAt(jx);
1322
 
                        }
1323
 
                    }
1324
 
                }
1325
 
                view = view.nextSiblingElement();
1326
 
            }
1327
 
 
1328
 
                mp->setFzz(true);
1329
 
        }
1330
 
 
1331
 
                m_binManager->addToTempPartsBin(mp);
1332
 
        addedToTemp = true;
1333
 
    }
1334
 
 
1335
 
        if (!addedToTemp) {
1336
 
                m_binManager->hideTempPartsBin();
1337
 
        }
1338
 
 
1339
 
        // the bundled itself
1340
 
        this->mainLoad(sketchName, "");
1341
 
        setCurrentFile(fileName, addToRecent, setAsLastOpened);
1342
 
}
1343
 
 
1344
 
void MainWindow::loadBundledNonAtomicEntity(const QString &fileName, Bundler* bundler, bool addToBin, bool dontAsk) {
1345
 
        QDir destFolder = QDir::temp();
1346
 
 
1347
 
        FolderUtils::createFolderAnCdIntoIt(destFolder, FolderUtils::getRandText());
1348
 
        QString unzipDirPath = destFolder.path();
1349
 
 
1350
 
        if(!FolderUtils::unzipTo(fileName, unzipDirPath)) {
1351
 
                QMessageBox::warning(
1352
 
                        this,
1353
 
                        tr("Fritzing"),
1354
 
                        tr("Unable to open shareable %1").arg(fileName)
1355
 
                );
1356
 
 
1357
 
                // gotta return now, or loadBundledSketchAux will crash
1358
 
                return;
1359
 
        }
1360
 
 
1361
 
        QDir unzipDir(unzipDirPath);
1362
 
 
1363
 
        if (bundler->preloadBundledAux(unzipDir, dontAsk)) {
1364
 
                QList<ModelPart*> mps = moveToPartsFolder(unzipDir,this,addToBin,true,FolderUtils::getUserDataStorePath("parts"),"contrib");
1365
 
                // the bundled itself
1366
 
                bundler->loadBundledAux(unzipDir,mps);
1367
 
        }
1368
 
 
1369
 
        FolderUtils::rmdir(unzipDirPath);
1370
 
}
1371
 
 
1372
 
/*
1373
 
void MainWindow::loadBundledPartFromWeb() {
1374
 
        QMainWindow *mw = new QMainWindow();
1375
 
        QString url = "http://localhost:8081/parts_gen/choose";
1376
 
        QWebView *view = new QWebView(mw);
1377
 
        mw->setCentralWidget(view);
1378
 
        view->setUrl(QUrl(url));
1379
 
        mw->show();
1380
 
        mw->raise();
1381
 
}
1382
 
*/
1383
 
 
1384
 
ModelPart* MainWindow::loadBundledPart(const QString &fileName, bool addToBin) {
1385
 
        QDir destFolder = QDir::temp();
1386
 
 
1387
 
        FolderUtils::createFolderAnCdIntoIt(destFolder, FolderUtils::getRandText());
1388
 
        QString unzipDirPath = destFolder.path();
1389
 
 
1390
 
        if(!FolderUtils::unzipTo(fileName, unzipDirPath)) {
1391
 
                QMessageBox::warning(
1392
 
                        this,
1393
 
                        tr("Fritzing"),
1394
 
                        tr("Unable to open shareable part %1").arg(fileName)
1395
 
                );
1396
 
                return NULL;
1397
 
        }
1398
 
 
1399
 
        QDir unzipDir(unzipDirPath);
1400
 
 
1401
 
        QList<ModelPart*> mps = moveToPartsFolder(unzipDir, this, addToBin, true, FolderUtils::getUserDataStorePath("parts"), "contrib");
1402
 
        if (mps.count()!=1) {
1403
 
                // if this fails, that means that the bundled was wrong
1404
 
                QMessageBox::warning(
1405
 
                        this,
1406
 
                        tr("Fritzing"),
1407
 
                        tr("Unable to read shareable part %1").arg(fileName)
1408
 
                );
1409
 
                return NULL;
1410
 
        }
1411
 
 
1412
 
        FolderUtils::rmdir(unzipDirPath);
1413
 
 
1414
 
        return mps[0];
1415
 
}
1416
 
 
1417
 
void MainWindow::saveBundledPart(const QString &moduleId) {
1418
 
        QString modIdToExport;
1419
 
        ModelPart* mp;
1420
 
 
1421
 
        if(moduleId.isEmpty()) {
1422
 
                if (m_currentGraphicsView == NULL) return;
1423
 
                PaletteItem *selectedPart = m_currentGraphicsView->getSelectedPart();
1424
 
                mp = selectedPart->modelPart();
1425
 
                modIdToExport = mp->moduleID();
1426
 
        } else {
1427
 
                modIdToExport = moduleId;
1428
 
                mp = m_refModel->retrieveModelPart(moduleId);
1429
 
        }
1430
 
        QString partTitle = mp->title();
1431
 
 
1432
 
        QString fileExt;
1433
 
        QString path = defaultSaveFolder()+"/"+partTitle+FritzingBundledPartExtension;
1434
 
        QString bundledFileName = FolderUtils::getSaveFileName(
1435
 
                        this,
1436
 
                        tr("Specify a file name"),
1437
 
                        path,
1438
 
                        tr("Fritzing Part (*%1)").arg(FritzingBundledPartExtension),
1439
 
                        &fileExt
1440
 
                  );
1441
 
 
1442
 
        if (bundledFileName.isEmpty()) return; // Cancel pressed
1443
 
 
1444
 
        if(!alreadyHasExtension(bundledFileName, FritzingBundledPartExtension)) {
1445
 
                bundledFileName += FritzingBundledPartExtension;
1446
 
        }
1447
 
 
1448
 
        QDir destFolder = QDir::temp();
1449
 
 
1450
 
        FolderUtils::createFolderAnCdIntoIt(destFolder, FolderUtils::getRandText());
1451
 
        QString dirToRemove = destFolder.path();
1452
 
 
1453
 
        QString aux = QFileInfo(bundledFileName).fileName();
1454
 
        QString destPartPath = // remove the last "z" from the extension
1455
 
                        destFolder.path()+"/"+aux.left(aux.size()-1);
1456
 
        DebugDialog::debug("saving part temporarily to "+destPartPath);
1457
 
 
1458
 
        //bool wasModified = isWindowModified();
1459
 
        //QString prevFileName = m_fileName;
1460
 
        //saveAsAux(destPartPath);
1461
 
        //m_fileName = prevFileName;
1462
 
        //setWindowModified(wasModified);
1463
 
        setTitle();
1464
 
 
1465
 
        saveBundledAux(mp, destFolder);
1466
 
 
1467
 
    QStringList skipSuffixes;
1468
 
        if(!FolderUtils::createZipAndSaveTo(destFolder, bundledFileName, skipSuffixes)) {
1469
 
                QMessageBox::warning(
1470
 
                        this,
1471
 
                        tr("Fritzing"),
1472
 
                        tr("Unable to export %1 to shareable sketch").arg(bundledFileName)
1473
 
                );
1474
 
        }
1475
 
 
1476
 
        FolderUtils::rmdir(dirToRemove);
1477
 
}
1478
 
 
1479
 
QStringList MainWindow::saveBundledAux(ModelPart *mp, const QDir &destFolder) {
1480
 
        QStringList names;
1481
 
        QString partPath = mp->modelPartShared()->path();
1482
 
        QFile file(partPath);
1483
 
        QString fn = ZIP_PART + QFileInfo(partPath).fileName();
1484
 
        names << fn;
1485
 
        file.copy(destFolder.path()+"/"+fn);
1486
 
 
1487
 
        QList<ViewIdentifierClass::ViewIdentifier> identifiers;
1488
 
        identifiers << ViewIdentifierClass::IconView << ViewIdentifierClass::BreadboardView << ViewIdentifierClass::SchematicView << ViewIdentifierClass::PCBView;
1489
 
        foreach (ViewIdentifierClass::ViewIdentifier viewIdentifier, identifiers) {
1490
 
                QString basename = mp->hasBaseNameFor(viewIdentifier);
1491
 
                if (basename.isEmpty()) continue;
1492
 
 
1493
 
                QString filename = ItemBase::getSvgFilename(mp, basename);
1494
 
                if (filename.isEmpty()) continue;
1495
 
 
1496
 
                QFile file(filename);
1497
 
                basename.replace("/", ".");
1498
 
                QString fn = ZIP_SVG + basename;
1499
 
                names << fn;
1500
 
                file.copy(destFolder.path()+"/"+fn);
1501
 
        }
1502
 
 
1503
 
        return names;
1504
 
}
1505
 
 
1506
 
QList<ModelPart*> MainWindow::moveToPartsFolder(QDir &unzipDir, MainWindow* mw, bool addToBin, bool addToAlien, const QString & prefixFolder, const QString &destFolder) {
1507
 
        QStringList namefilters;
1508
 
        QList<ModelPart*> retval;
1509
 
 
1510
 
        if (mw == NULL) {
1511
 
                throw "MainWindow::moveToPartsFolder mainwindow missing";
1512
 
        }
1513
 
 
1514
 
        if(mw) {
1515
 
                namefilters << ZIP_SVG+"*";
1516
 
                foreach(QFileInfo file, unzipDir.entryInfoList(namefilters)) { // svg files
1517
 
                        //DebugDialog::debug("unzip svg " + file.absoluteFilePath());
1518
 
                        mw->copyToSvgFolder(file, addToAlien, prefixFolder, destFolder);
1519
 
                }
1520
 
 
1521
 
                namefilters.clear();
1522
 
                namefilters << ZIP_PART+"*"; 
1523
 
 
1524
 
                foreach(QFileInfo file, unzipDir.entryInfoList(namefilters)) { // part files
1525
 
                        //DebugDialog::debug("unzip part " + file.absoluteFilePath());
1526
 
                        retval << mw->copyToPartsFolder(file, addToBin, addToAlien, prefixFolder, destFolder);
1527
 
                }
1528
 
        }
1529
 
 
1530
 
        return retval;
1531
 
}
1532
 
 
1533
 
void MainWindow::copyToSvgFolder(const QFileInfo& file, bool addToAlien, const QString & prefixFolder, const QString &destFolder) {
1534
 
        QFile svgfile(file.filePath());
1535
 
        // let's make sure that we remove just the suffix
1536
 
        QString fileName = file.fileName().remove(QRegExp("^"+ZIP_SVG));
1537
 
        QString viewFolder = fileName.left(fileName.indexOf("."));
1538
 
        fileName.remove(0, viewFolder.length() + 1);
1539
 
 
1540
 
        QString destFilePath =
1541
 
                prefixFolder+"/svg/"+destFolder+"/"+viewFolder+"/"+fileName;
1542
 
 
1543
 
        backupExistingFileIfExists(destFilePath);
1544
 
        if(svgfile.copy(destFilePath)) {
1545
 
                if (addToAlien) {
1546
 
                        m_alienFiles << destFilePath;
1547
 
                }
1548
 
        }
1549
 
}
1550
 
 
1551
 
ModelPart* MainWindow::copyToPartsFolder(const QFileInfo& file, bool addToBin, bool addToAlien, const QString & prefixFolder, const QString &destFolder) {
1552
 
        QFile partfile(file.filePath());
1553
 
        // let's make sure that we remove just the suffix
1554
 
        QString destFilePath =
1555
 
                prefixFolder+"/"+destFolder+"/"+file.fileName().remove(QRegExp("^"+ZIP_PART));
1556
 
 
1557
 
        backupExistingFileIfExists(destFilePath);
1558
 
        if(partfile.copy(destFilePath)) {
1559
 
                if (addToAlien) {
1560
 
                        m_alienFiles << destFilePath;
1561
 
                        m_alienPartsMsg = tr("Do you want to keep the imported parts?");
1562
 
                }
1563
 
        }
1564
 
        ModelPart *mp = m_refModel->loadPart(destFilePath, true, false);
1565
 
        mp->setAlien(true);
1566
 
 
1567
 
        if(addToBin) {
1568
 
                m_binManager->addToContrib(mp);
1569
 
        }
1570
 
 
1571
 
        return mp;
1572
 
}
1573
 
 
1574
 
void MainWindow::binSaved(bool hasPartsFromBundled) {
1575
 
        if(hasPartsFromBundled) {
1576
 
                // the bin will need those parts, so just keep them
1577
 
                m_alienFiles.clear();
1578
 
                resetTempFolder();
1579
 
        }
1580
 
}
1581
 
 
1582
 
#undef ZIP_PART
1583
 
#undef ZIP_SVG
1584
 
 
1585
 
 
1586
 
void MainWindow::backupExistingFileIfExists(const QString &destFilePath) {
1587
 
        if(QFileInfo(destFilePath).exists()) {
1588
 
                if(m_tempDir.path() == ".") {
1589
 
                        m_tempDir = QDir::temp();
1590
 
                        FolderUtils::createFolderAnCdIntoIt(m_tempDir, FolderUtils::getRandText());
1591
 
                        DebugDialog::debug("debug folder for overwritten files: "+m_tempDir.path());
1592
 
                }
1593
 
 
1594
 
                QString fileBackupName = QFileInfo(destFilePath).fileName();
1595
 
                m_filesReplacedByAlienOnes << destFilePath;
1596
 
                QFile file(destFilePath);
1597
 
                bool alreadyExists = file.exists();
1598
 
                file.copy(m_tempDir.path()+"/"+fileBackupName);
1599
 
 
1600
 
                if(alreadyExists) {
1601
 
                        file.remove(destFilePath);
1602
 
                }
1603
 
        }
1604
 
}
1605
 
 
1606
 
void MainWindow::recoverBackupedFiles() {
1607
 
        foreach(QString originalFilePath, m_filesReplacedByAlienOnes) {
1608
 
                QFile file(m_tempDir.path()+"/"+QFileInfo(originalFilePath).fileName());
1609
 
                if(file.exists(originalFilePath)) {
1610
 
                        file.remove();
1611
 
                }
1612
 
                file.copy(originalFilePath);
1613
 
        }
1614
 
        resetTempFolder();
1615
 
}
1616
 
 
1617
 
void MainWindow::resetTempFolder() {
1618
 
        if(m_tempDir.path() != ".") {
1619
 
                FolderUtils::rmdir(m_tempDir);
1620
 
                m_tempDir = QDir::temp();
1621
 
        }
1622
 
        m_filesReplacedByAlienOnes.clear();
1623
 
}
1624
 
 
1625
 
void MainWindow::routingStatusSlot(SketchWidget * sketchWidget, const RoutingStatus & routingStatus) {
1626
 
        m_routingStatus = routingStatus;
1627
 
        QString theText;
1628
 
        if (routingStatus.m_netCount == 0) {
1629
 
                theText = tr("No connections to route");
1630
 
        } else if (routingStatus.m_netCount == routingStatus.m_netRoutedCount) {
1631
 
                if (routingStatus.m_jumperItemCount == 0) {
1632
 
                        theText = tr("Routing completed");
1633
 
                }
1634
 
                else {
1635
 
                        theText = tr("Routing completed using %n jumper part(s)", "", routingStatus.m_jumperItemCount);
1636
 
                }
1637
 
        } else {
1638
 
                theText = tr("%1 of %2 nets routed - %n connector(s) still to be routed", "", routingStatus.m_connectorsLeftToRoute)
1639
 
                        .arg(routingStatus.m_netRoutedCount)
1640
 
                        .arg(routingStatus.m_netCount);
1641
 
        }
1642
 
 
1643
 
        dynamic_cast<SketchAreaWidget *>(sketchWidget->parent())->routingStatusLabel()->setLabelText(theText);
1644
 
 
1645
 
        updateTraceMenu();
1646
 
}
1647
 
 
1648
 
void MainWindow::applyReadOnlyChange(bool isReadOnly) {
1649
 
        Q_UNUSED(isReadOnly);
1650
 
        //m_saveAct->setDisabled(isReadOnly);
1651
 
}
1652
 
 
1653
 
void MainWindow::currentNavigatorChanged(MiniViewContainer * miniView)
1654
 
{
1655
 
        int index = m_navigators.indexOf(miniView);
1656
 
        if (index < 0) return;
1657
 
 
1658
 
        int oldIndex = m_tabWidget->currentIndex();
1659
 
        if (oldIndex == index) return;
1660
 
 
1661
 
        this->m_tabWidget->setCurrentIndex(index);
1662
 
}
1663
 
 
1664
 
void MainWindow::viewSwitchedTo(int viewIndex) {
1665
 
        m_tabWidget->setCurrentIndex(viewIndex);
1666
 
}
1667
 
 
1668
 
const QString MainWindow::fritzingTitle() {
1669
 
        if (m_currentGraphicsView == NULL) {
1670
 
                return FritzingWindow::fritzingTitle();
1671
 
        }
1672
 
 
1673
 
        QString fritzing = FritzingWindow::fritzingTitle();
1674
 
        return tr("%1 - [%2]").arg(fritzing).arg(m_currentGraphicsView->viewName());
1675
 
}
1676
 
 
1677
 
QAction *MainWindow::raiseWindowAction() {
1678
 
        return m_raiseWindowAct;
1679
 
}
1680
 
 
1681
 
void MainWindow::raiseAndActivate() {
1682
 
        if(isMinimized()) {
1683
 
                showNormal();
1684
 
        }
1685
 
        raise();
1686
 
        QTimer::singleShot(20, this, SLOT(activateWindowAux()));
1687
 
}
1688
 
 
1689
 
void MainWindow::activateWindowAux() {
1690
 
        activateWindow();
1691
 
}
1692
 
 
1693
 
void MainWindow::updateRaiseWindowAction() {
1694
 
        QString actionText;
1695
 
        QFileInfo fileInfo(m_fwFilename);
1696
 
        if(fileInfo.exists()) {
1697
 
                int lastSlashIdx = m_fwFilename.lastIndexOf("/");
1698
 
                int beforeLastSlashIdx = m_fwFilename.left(lastSlashIdx).lastIndexOf("/");
1699
 
                actionText = beforeLastSlashIdx > -1 && lastSlashIdx > -1 ? "..." : "";
1700
 
                actionText += m_fwFilename.right(m_fwFilename.size()-beforeLastSlashIdx-1);
1701
 
        } else {
1702
 
                actionText = m_fwFilename;
1703
 
        }
1704
 
        m_raiseWindowAct->setText(actionText);
1705
 
        m_raiseWindowAct->setToolTip(m_fwFilename);
1706
 
        m_raiseWindowAct->setStatusTip("raise \""+m_fwFilename+"\" window");
1707
 
}
1708
 
 
1709
 
QSizeGrip *MainWindow::sizeGrip() {
1710
 
        return m_sizeGrip;
1711
 
}
1712
 
 
1713
 
QStatusBar *MainWindow::realStatusBar() {
1714
 
        return m_statusBar;
1715
 
}
1716
 
 
1717
 
void MainWindow::moveEvent(QMoveEvent * event) {
1718
 
        FritzingWindow::moveEvent(event);
1719
 
        emit mainWindowMoved(this);
1720
 
}
1721
 
 
1722
 
bool MainWindow::event(QEvent * e) {
1723
 
        switch (e->type()) {
1724
 
                case QEvent::WindowActivate:
1725
 
                        emit changeActivationSignal(true, this);
1726
 
                        break;
1727
 
                case QEvent::WindowDeactivate:
1728
 
                        emit changeActivationSignal(false, this);
1729
 
                        break;
1730
 
                default:
1731
 
                        break;
1732
 
        }
1733
 
        return FritzingWindow::event(e);
1734
 
}
1735
 
 
1736
 
void MainWindow::resizeEvent(QResizeEvent * event) {
1737
 
        m_sizeGrip->rearrange();
1738
 
        FritzingWindow::resizeEvent(event);
1739
 
}
1740
 
 
1741
 
void MainWindow::showInViewHelp() {
1742
 
        //delete m_helper;
1743
 
        if (m_helper == NULL) {
1744
 
                m_helper = new Helper(this, true);
1745
 
                return;
1746
 
        }
1747
 
 
1748
 
        bool toggle = !m_helper->helpVisible(m_tabWidget->currentIndex());
1749
 
        showAllFirstTimeHelp(toggle);
1750
 
 
1751
 
        /*
1752
 
        m_helper->toggleHelpVisibility(m_tabWidget->currentIndex());
1753
 
        */
1754
 
 
1755
 
        m_showInViewHelpAct->setChecked(m_helper->helpVisible(m_tabWidget->currentIndex()));
1756
 
}
1757
 
 
1758
 
 
1759
 
void MainWindow::showAllFirstTimeHelp(bool show) {
1760
 
        if (m_helper) {
1761
 
                for (int i = 0; i < 3; i++) {
1762
 
                        m_helper->setHelpVisibility(i, show);
1763
 
                }
1764
 
        }
1765
 
        m_showInViewHelpAct->setChecked(show);
1766
 
}
1767
 
 
1768
 
void MainWindow::enableCheckUpdates(bool enabled)
1769
 
{
1770
 
        if (m_checkForUpdatesAct != NULL) {
1771
 
                m_checkForUpdatesAct->setEnabled(enabled);
1772
 
        }
1773
 
}
1774
 
 
1775
 
 
1776
 
void MainWindow::swapSelectedDelay(const QString & family, const QString & prop, QMap<QString, QString> & currPropsMap, ItemBase * itemBase) 
1777
 
{
1778
 
        m_swapTimer.stop();
1779
 
        m_swapTimer.setAll(family, prop, currPropsMap, itemBase);
1780
 
        m_swapTimer.start();
1781
 
}
1782
 
 
1783
 
void MainWindow::swapSelectedTimeout()
1784
 
{
1785
 
        if (sender() == &m_swapTimer) {
1786
 
                QMap<QString, QString> map =  m_swapTimer.propsMap();
1787
 
                swapSelectedMap(m_swapTimer.family(), m_swapTimer.prop(), map, m_swapTimer.itemBase());
1788
 
        }
1789
 
}
1790
 
 
1791
 
void MainWindow::swapSelectedMap(const QString & family, const QString & prop, QMap<QString, QString> & currPropsMap, ItemBase * itemBase) 
1792
 
{
1793
 
        if (itemBase == NULL) return;
1794
 
 
1795
 
        QString generatedModuleID = currPropsMap.value("moduleID");
1796
 
 
1797
 
        if (generatedModuleID.isEmpty()) {
1798
 
            if ((family.compare("logo") == 0 || family.compare("pad") == 0) && prop.compare("layer") == 0) {
1799
 
                    QString value = currPropsMap.value(prop);
1800
 
                    if (value.contains("1") && m_currentGraphicsView->boardLayers() == 1) {
1801
 
                            QMessageBox::warning(
1802
 
                                    this,
1803
 
                                    tr("No copper top layer"),
1804
 
                                    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.")
1805
 
                            );
1806
 
                            return;
1807
 
                    }
1808
 
            }
1809
 
    }
1810
 
 
1811
 
        if (generatedModuleID.isEmpty()) {
1812
 
                if (family.compare("Prototyping Board", Qt::CaseInsensitive) == 0) {
1813
 
                        if (prop.compare("size", Qt::CaseInsensitive) == 0 || prop.compare("type", Qt::CaseInsensitive) == 0) {
1814
 
                                QString size = currPropsMap.value("size");
1815
 
                                QString type = currPropsMap.value("type");
1816
 
                                if (type.compare("perfboard", Qt::CaseInsensitive) == 0) {
1817
 
                                        generatedModuleID = Perfboard::genModuleID(currPropsMap);
1818
 
                                }
1819
 
                                else if (type.compare("stripboard", Qt::CaseInsensitive) == 0) {
1820
 
                                        generatedModuleID = Stripboard::genModuleID(currPropsMap);
1821
 
                                }
1822
 
                        }
1823
 
                }
1824
 
        }
1825
 
 
1826
 
        if (!generatedModuleID.isEmpty()) {
1827
 
                ModelPart * modelPart = m_refModel->retrieveModelPart(generatedModuleID);
1828
 
                if (modelPart == NULL) {
1829
 
                        if (!m_refModel->genFZP(generatedModuleID, m_refModel)) {
1830
 
                                return;
1831
 
                        }
1832
 
                }
1833
 
 
1834
 
                swapSelectedAux(itemBase->layerKinChief(), generatedModuleID);
1835
 
                return;
1836
 
        }
1837
 
 
1838
 
        if ((prop.compare("package", Qt::CaseSensitive) != 0) && swapSpecial(prop, currPropsMap)) {
1839
 
                return;
1840
 
        }
1841
 
 
1842
 
        foreach (QString key, currPropsMap.keys()) {
1843
 
                QString value = currPropsMap.value(key);
1844
 
                m_refModel->recordProperty(key, value);
1845
 
        }
1846
 
 
1847
 
        QString moduleID = m_refModel->retrieveModuleIdWith(family, prop, true);
1848
 
        bool exactMatch = m_refModel->lastWasExactMatch();
1849
 
 
1850
 
        if(moduleID.isEmpty()) {
1851
 
                QMessageBox::information(
1852
 
                        this,
1853
 
                        tr("Sorry!"),
1854
 
                        tr(
1855
 
                         "No part with those characteristics.\n"
1856
 
                         "We're working to avoid this message, and only let you choose between properties that do exist")
1857
 
                );
1858
 
                return;
1859
 
        }
1860
 
 
1861
 
 
1862
 
 
1863
 
        itemBase = itemBase->layerKinChief();
1864
 
 
1865
 
        if(!exactMatch) {
1866
 
                AutoCloseMessageBox::showMessage(this, tr("No exactly matching part found; Fritzing chose the closest match."));
1867
 
        }
1868
 
 
1869
 
        swapSelectedAux(itemBase, moduleID);
1870
 
}
1871
 
 
1872
 
bool MainWindow::swapSpecial(const QString & theProp, QMap<QString, QString> & currPropsMap) {
1873
 
        ItemBase * itemBase = m_infoView->currentItem();
1874
 
        QString pinSpacing, resistance;
1875
 
    int layers = 0;
1876
 
 
1877
 
        foreach (QString key, currPropsMap.keys()) {
1878
 
                if (key.compare("layers", Qt::CaseInsensitive) == 0) {
1879
 
                        if (!Board::isBoard(itemBase)) continue;
1880
 
 
1881
 
                        QString value = currPropsMap.value(key, "");
1882
 
                        if (value.compare(Board::OneLayerTranslated) == 0) {
1883
 
                                layers = 1;
1884
 
                        }
1885
 
                        else if (value.compare(Board::TwoLayersTranslated) == 0) {
1886
 
                                layers = 2;
1887
 
                        }
1888
 
        }
1889
 
 
1890
 
                if (key.compare("resistance", Qt::CaseInsensitive) == 0) {
1891
 
                        resistance = currPropsMap.value(key);
1892
 
                        continue;
1893
 
                }
1894
 
                if (key.compare("pin spacing", Qt::CaseInsensitive) == 0) {
1895
 
                        pinSpacing = currPropsMap.value(key);
1896
 
                        continue;
1897
 
                }
1898
 
        }
1899
 
 
1900
 
    if (layers != 0) {
1901
 
        currPropsMap.insert("layers", QString::number(layers));
1902
 
        if (theProp.compare("layers") == 0) {
1903
 
            QString msg = (layers == 1) ? tr("Change to single layer pcb") : tr("Change to two layer pcb");
1904
 
            swapLayers(itemBase, layers, msg, true, SketchWidget::PropChangeDelay);
1905
 
            return true;
1906
 
        }
1907
 
        }
1908
 
 
1909
 
 
1910
 
        if (!resistance.isEmpty() || !pinSpacing.isEmpty()) {
1911
 
                if (theProp.contains("band", Qt::CaseInsensitive)) {
1912
 
                        // swap 4band for 5band or vice versa.
1913
 
                        return false;
1914
 
                }
1915
 
 
1916
 
                Resistor * resistor = qobject_cast<Resistor *>(itemBase);
1917
 
                if (resistor != NULL) {
1918
 
                        m_currentGraphicsView->setResistance(resistance, pinSpacing);
1919
 
                        return true;
1920
 
                }
1921
 
        }
1922
 
 
1923
 
        return false;
1924
 
}
1925
 
 
1926
 
void MainWindow::swapLayers(ItemBase * itemBase, int layers, const QString & msg, bool flip, int delay) {
1927
 
    QUndoCommand* parentCommand = new QUndoCommand(msg);
1928
 
        new CleanUpWiresCommand(m_breadboardGraphicsView, CleanUpWiresCommand::UndoOnly, parentCommand);
1929
 
    m_pcbGraphicsView->swapLayers(itemBase, layers, flip, parentCommand);
1930
 
        // need to defer execution so the content of the info view doesn't change during an event that started in the info view
1931
 
        m_undoStack->waitPush(parentCommand, delay);
1932
 
}
1933
 
 
1934
 
void MainWindow::swapSelectedAux(ItemBase * itemBase, const QString & moduleID) {
1935
 
 
1936
 
        QUndoCommand* parentCommand = new QUndoCommand(tr("Swapped %1 with module %2").arg(itemBase->instanceTitle()).arg(moduleID));
1937
 
        new CleanUpWiresCommand(m_breadboardGraphicsView, CleanUpWiresCommand::UndoOnly, parentCommand);
1938
 
        swapSelectedAuxAux(itemBase, moduleID, itemBase->viewLayerSpec(), parentCommand);
1939
 
    
1940
 
        // need to defer execution so the content of the info view doesn't change during an event that started in the info view
1941
 
        m_undoStack->waitPush(parentCommand, SketchWidget::PropChangeDelay);
1942
 
 
1943
 
        warnSMD(moduleID);
1944
 
}
1945
 
 
1946
 
void MainWindow::swapBoardImageSlot(SketchWidget * sketchWidget, ItemBase * itemBase, const QString & filename, const QString & moduleID, bool addName) {
1947
 
 
1948
 
        QUndoCommand* parentCommand = new QUndoCommand(tr("Change image to %2").arg(filename));
1949
 
        long newID = swapSelectedAuxAux(itemBase, moduleID, itemBase->viewLayerSpec(), parentCommand);
1950
 
 
1951
 
    LoadLogoImageCommand * cmd = new LoadLogoImageCommand(sketchWidget, newID, "", QSizeF(0,0), filename, filename, addName, parentCommand);
1952
 
    cmd->setRedoOnly();
1953
 
   
1954
 
        // need to defer execution so the content of the info view doesn't change during an event that started in the info view
1955
 
        m_undoStack->waitPush(parentCommand, SketchWidget::PropChangeDelay);
1956
 
}
1957
 
 
1958
 
 
1959
 
void MainWindow::subSwapSlot(SketchWidget * sketchWidget, ItemBase * itemBase, const QString & newModuleID, ViewLayer::ViewLayerSpec viewLayerSpec, long & newID, QUndoCommand * parentCommand) {
1960
 
        Q_UNUSED(sketchWidget);
1961
 
        newID = swapSelectedAuxAux(itemBase, newModuleID, viewLayerSpec, parentCommand);
1962
 
}
1963
 
 
1964
 
long MainWindow::swapSelectedAuxAux(ItemBase * itemBase, const QString & moduleID,  ViewLayer::ViewLayerSpec viewLayerSpec, QUndoCommand * parentCommand) 
1965
 
{
1966
 
        long modelIndex = ModelPart::nextIndex();
1967
 
 
1968
 
        QList<SketchWidget *> sketchWidgets;
1969
 
 
1970
 
    // master view must go last, since it creates the delete command, and possibly has all the local props
1971
 
    switch (itemBase->viewIdentifier()) {
1972
 
        case ViewIdentifierClass::SchematicView:
1973
 
                    sketchWidgets << m_pcbGraphicsView << m_breadboardGraphicsView << m_schematicGraphicsView;
1974
 
            break;
1975
 
        case ViewIdentifierClass::PCBView:
1976
 
            sketchWidgets << m_schematicGraphicsView << m_breadboardGraphicsView << m_pcbGraphicsView;
1977
 
            break;
1978
 
        default:
1979
 
            sketchWidgets << m_schematicGraphicsView << m_pcbGraphicsView << m_breadboardGraphicsView;
1980
 
            break;
1981
 
        }
1982
 
 
1983
 
    SwapThing swapThing;
1984
 
    swapThing.firstTime = true;
1985
 
    swapThing.itemBase = itemBase;
1986
 
    swapThing.newModelIndex = modelIndex;
1987
 
    swapThing.newModuleID = moduleID;
1988
 
    swapThing.viewLayerSpec = viewLayerSpec;
1989
 
    swapThing.parentCommand = parentCommand;
1990
 
 
1991
 
    long newID = 0;
1992
 
    for (int i = 0; i < 3; i++) {
1993
 
        long tempID = sketchWidgets[i]->setUpSwap(swapThing, i == 2);
1994
 
        if (newID == 0 && tempID != 0) newID = tempID;
1995
 
    }
1996
 
 
1997
 
        // TODO:  z-order?
1998
 
 
1999
 
        return newID;
2000
 
}
2001
 
 
2002
 
void MainWindow::svgMissingLayer(const QString & layername, const QString & path) {
2003
 
        QMessageBox::warning(
2004
 
                this,
2005
 
                tr("Fritzing"),
2006
 
                tr("Svg %1 is missing a '%2' layer. "
2007
 
                        "For more information on how to create a custom board shape, "
2008
 
                        "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>.")
2009
 
                .arg(path)
2010
 
                .arg(layername)
2011
 
        );
2012
 
}
2013
 
 
2014
 
void MainWindow::addDefaultParts() {
2015
 
        if (m_pcbGraphicsView == NULL) return;
2016
 
 
2017
 
        m_pcbGraphicsView->addDefaultParts();
2018
 
        m_breadboardGraphicsView->addDefaultParts();
2019
 
        m_schematicGraphicsView->addDefaultParts();
2020
 
}
2021
 
 
2022
 
MainWindow * MainWindow::newMainWindow(PaletteModel * paletteModel, ReferenceModel *refModel, const QString & displayPath, bool showProgress, bool lockFiles) {
2023
 
    MainWindow * mw = new MainWindow(paletteModel, refModel, NULL);
2024
 
        if (showProgress) {
2025
 
                mw->showFileProgressDialog(displayPath);
2026
 
        }
2027
 
 
2028
 
    mw->init(paletteModel, refModel, lockFiles);
2029
 
 
2030
 
        return mw;
2031
 
}
2032
 
 
2033
 
void  MainWindow::clearFileProgressDialog() {
2034
 
        if (m_fileProgressDialog) {
2035
 
                m_fileProgressDialog->close();
2036
 
                delete m_fileProgressDialog;
2037
 
                m_fileProgressDialog = NULL;
2038
 
        }
2039
 
}
2040
 
 
2041
 
void MainWindow::setFileProgressPath(const QString & path)
2042
 
{
2043
 
        if (m_fileProgressDialog) m_fileProgressDialog->setMessage(tr("loading %1").arg(path));
2044
 
}
2045
 
 
2046
 
FileProgressDialog * MainWindow::fileProgressDialog()
2047
 
{
2048
 
        return m_fileProgressDialog;
2049
 
}
2050
 
 
2051
 
void MainWindow::showFileProgressDialog(const QString & path) {
2052
 
    m_fileProgressDialog = new FileProgressDialog(tr("Loading..."), 200, this);
2053
 
        m_fileProgressDialog->setBinLoadingChunk(50);
2054
 
        if (!path.isEmpty()) {
2055
 
                setFileProgressPath(QFileInfo(path).fileName());
2056
 
        }
2057
 
        else {
2058
 
                setFileProgressPath(tr("new sketch"));
2059
 
        }
2060
 
}
2061
 
 
2062
 
const QString &MainWindow::selectedModuleID() {
2063
 
        if(m_currentGraphicsView) {
2064
 
                return m_currentGraphicsView->selectedModuleID();
2065
 
        } else {
2066
 
                return ___emptyString___;
2067
 
        }
2068
 
}
2069
 
 
2070
 
void MainWindow::redrawSketch() {
2071
 
        foreach (QGraphicsItem * item, m_currentGraphicsView->scene()->items()) {
2072
 
                item->update();
2073
 
                ConnectorItem * c = dynamic_cast<ConnectorItem *>(item);
2074
 
                if (c != NULL) {
2075
 
                        c->restoreColor(false, 0, true);
2076
 
                }
2077
 
        }
2078
 
}
2079
 
 
2080
 
void MainWindow::statusMessage(QString message, int timeout) {
2081
 
        QStatusBar * sb = realStatusBar();
2082
 
        if (sb != NULL) {
2083
 
                sb->showMessage(message, timeout);
2084
 
        }
2085
 
}
2086
 
 
2087
 
void MainWindow::dropPaste(SketchWidget * sketchWidget) {
2088
 
        Q_UNUSED(sketchWidget);
2089
 
        pasteInPlace();
2090
 
}
2091
 
 
2092
 
void MainWindow::updateLayerMenuSlot() {
2093
 
        updateLayerMenu(true);
2094
 
}
2095
 
 
2096
 
bool MainWindow::save() {
2097
 
        bool result = FritzingWindow::save();
2098
 
        if (result) {
2099
 
                QSettings settings;
2100
 
                settings.setValue("lastOpenSketch", m_fwFilename);
2101
 
        }
2102
 
        return result;
2103
 
}
2104
 
 
2105
 
bool MainWindow::saveAs() {
2106
 
        bool result = false;
2107
 
        if (m_fwFilename.endsWith(FritzingSketchExtension)) {
2108
 
                result = FritzingWindow::saveAs(m_fwFilename + 'z', false);
2109
 
        }
2110
 
        else {
2111
 
                result = FritzingWindow::saveAs();
2112
 
        }
2113
 
        if (result) {
2114
 
                QSettings settings;
2115
 
                settings.setValue("lastOpenSketch", m_fwFilename);
2116
 
        }
2117
 
        return result;
2118
 
}
2119
 
 
2120
 
void MainWindow::changeBoardLayers(int layers, bool doEmit) {
2121
 
        Q_UNUSED(doEmit);
2122
 
        Q_UNUSED(layers);
2123
 
        updateActiveLayerButtons();
2124
 
        m_currentGraphicsView->updateConnectors();
2125
 
}
2126
 
 
2127
 
void MainWindow::updateActiveLayerButtons() {
2128
 
        int index = activeLayerIndex();
2129
 
        bool enabled = index >= 0;
2130
 
 
2131
 
        m_activeLayerButtonWidget->setCurrentIndex(index);
2132
 
        m_activeLayerButtonWidget->setVisible(enabled);
2133
 
 
2134
 
        m_activeLayerBothAct->setEnabled(enabled);
2135
 
        m_activeLayerBottomAct->setEnabled(enabled);
2136
 
        m_activeLayerTopAct->setEnabled(enabled);
2137
 
 
2138
 
        QList<QAction *> actions;
2139
 
        actions << m_activeLayerBothAct << m_activeLayerBottomAct << m_activeLayerTopAct;
2140
 
        setActionsIcons(index, actions);
2141
 
}
2142
 
 
2143
 
 
2144
 
int MainWindow::activeLayerIndex() 
2145
 
{
2146
 
        if (m_currentGraphicsView->boardLayers() == 2) {
2147
 
                bool copper0Visible = m_currentGraphicsView->layerIsActive(ViewLayer::Copper0);
2148
 
                bool copper1Visible = m_currentGraphicsView->layerIsActive(ViewLayer::Copper1);
2149
 
                if (copper0Visible && copper1Visible) {
2150
 
                        return 0;
2151
 
                }
2152
 
                else if (copper1Visible) {
2153
 
                        return 2;
2154
 
                }
2155
 
                else if (copper0Visible) {
2156
 
                        return 1;
2157
 
                }
2158
 
        }
2159
 
 
2160
 
        return -1;
2161
 
}
2162
 
 
2163
 
/**
2164
 
 * A slot for saving a copy of the current sketch to a temp location.
2165
 
 * This should be called every X minutes as well as just before certain
2166
 
 * events, such as saves, part imports, file export/printing. This relies
2167
 
 * on the m_autosaveNeeded variable and the undoStack being dirty for
2168
 
 * an autosave to be attempted.
2169
 
 */
2170
 
void  MainWindow::backupSketch() {
2171
 
        if (ProcessEventBlocker::isProcessing()) {
2172
 
                // don't want to autosave during autorouting, for example
2173
 
                return;
2174
 
        }
2175
 
 
2176
 
    if (m_autosaveNeeded && !m_undoStack->isClean()) {
2177
 
        m_autosaveNeeded = false;                       // clear this now in case the save takes a really long time
2178
 
 
2179
 
        DebugDialog::debug(QString("%1 autosaved as %2").arg(m_fwFilename).arg(m_backupFileNameAndPath));
2180
 
        statusBar()->showMessage(tr("Backing up '%1'").arg(m_fwFilename), 2000);
2181
 
                ProcessEventBlocker::processEvents();
2182
 
                m_backingUp = true;
2183
 
                connectStartSave(true);
2184
 
                m_sketchModel->save(m_backupFileNameAndPath, false);
2185
 
                connectStartSave(false);
2186
 
                m_backingUp = false;
2187
 
    }
2188
 
}
2189
 
 
2190
 
/**
2191
 
 * This function is used to trigger an autosave at the next autosave
2192
 
 * timer event. It is connected to the QUndoStack::indexChanged(int)
2193
 
 * signal so that any change to the undo stack triggers autosaves.
2194
 
 * This function can be called independent of this signal and
2195
 
 * still work properly.
2196
 
 */
2197
 
void MainWindow::autosaveNeeded(int index) {
2198
 
    Q_UNUSED(index);
2199
 
    //DebugDialog::debug(QString("Triggering autosave"));
2200
 
    m_autosaveNeeded = true;
2201
 
}
2202
 
 
2203
 
/**
2204
 
 * delete the backup file when the undostack is clean.
2205
 
 */
2206
 
void MainWindow::undoStackCleanChanged(bool isClean) {
2207
 
    DebugDialog::debug(QString("Clean status changed to %1").arg(isClean));
2208
 
    if (isClean) {
2209
 
        QFile::remove(m_backupFileNameAndPath);
2210
 
    }
2211
 
}
2212
 
 
2213
 
void MainWindow::setAutosavePeriod(int minutes) {
2214
 
        setAutosave(minutes, AutosaveEnabled);
2215
 
}
2216
 
 
2217
 
void MainWindow::setAutosaveEnabled(bool enabled) {
2218
 
        setAutosave(AutosaveTimeoutMinutes, enabled);
2219
 
}
2220
 
 
2221
 
void MainWindow::setAutosave(int minutes, bool enabled) {
2222
 
        AutosaveTimeoutMinutes = minutes;
2223
 
        AutosaveEnabled = enabled;
2224
 
        foreach (QWidget * widget, QApplication::topLevelWidgets()) {
2225
 
                MainWindow * mainWindow = qobject_cast<MainWindow *>(widget);
2226
 
                if (mainWindow == NULL) continue;
2227
 
 
2228
 
                mainWindow->m_autosaveTimer.stop();
2229
 
                if (AutosaveEnabled) {
2230
 
                        // is there a way to get the current timer offset so that all the timers aren't running in sync?
2231
 
                        // or just add some random time...
2232
 
                        mainWindow->m_autosaveTimer.start(AutosaveTimeoutMinutes * 60 * 1000);
2233
 
                }
2234
 
        }
2235
 
}
2236
 
 
2237
 
bool MainWindow::hasLinkedProgramFiles(const QString & filename, QStringList & linkedProgramFiles) 
2238
 
{
2239
 
        QFile file(filename);
2240
 
        file.open(QFile::ReadOnly);
2241
 
        QXmlStreamReader xml(&file);
2242
 
    xml.setNamespaceProcessing(false);
2243
 
 
2244
 
        bool done = false;
2245
 
        while (!xml.atEnd()) {
2246
 
        switch (xml.readNext()) {
2247
 
        case QXmlStreamReader::StartElement:
2248
 
                        if (xml.name().toString().compare("program") == 0) {
2249
 
                                linkedProgramFiles.append(xml.readElementText());
2250
 
                                break;
2251
 
                        }
2252
 
                        if (xml.name().toString().compare("views") == 0) {
2253
 
                                done = true;
2254
 
                                break;
2255
 
                        }
2256
 
                        if (xml.name().toString().compare("instances") == 0) {
2257
 
                                done = true;
2258
 
                                break;
2259
 
                        }
2260
 
                default:
2261
 
                        break;
2262
 
                }
2263
 
 
2264
 
                if (done) break;
2265
 
        }
2266
 
 
2267
 
        return linkedProgramFiles.count() > 0;
2268
 
}
2269
 
 
2270
 
QString MainWindow::getExtensionString() {
2271
 
        return tr("Fritzing (*%1)").arg(fileExtension());
2272
 
}
2273
 
 
2274
 
QStringList MainWindow::getExtensions() {
2275
 
        QStringList extensions;
2276
 
        extensions.append(fileExtension());
2277
 
        return extensions;
2278
 
}
2279
 
 
2280
 
void MainWindow::firstTimeHelpHidden() {
2281
 
        m_showInViewHelpAct->setChecked(false);
2282
 
}
2283
 
 
2284
 
void MainWindow::routingStatusLabelMousePress(QMouseEvent* event) {
2285
 
        routingStatusLabelMouse(event, true);
2286
 
}
2287
 
 
2288
 
void MainWindow::routingStatusLabelMouseRelease(QMouseEvent* event) {
2289
 
        routingStatusLabelMouse(event, false);
2290
 
}
2291
 
 
2292
 
void MainWindow::routingStatusLabelMouse(QMouseEvent*, bool show) {
2293
 
        if (show) DebugDialog::debug("-------");
2294
 
 
2295
 
        QSet<ConnectorItem *> toShow;
2296
 
        foreach (QGraphicsItem * item, m_currentGraphicsView->scene()->items()) {
2297
 
                VirtualWire * vw = dynamic_cast<VirtualWire *>(item);
2298
 
                if (vw == NULL) continue;
2299
 
 
2300
 
                foreach (ConnectorItem * connectorItem, vw->connector0()->connectedToItems()) {
2301
 
                        toShow.insert(connectorItem);
2302
 
                }
2303
 
                foreach (ConnectorItem * connectorItem, vw->connector1()->connectedToItems()) {
2304
 
                        toShow.insert(connectorItem);
2305
 
                }
2306
 
        }
2307
 
        foreach (ConnectorItem * connectorItem, toShow) {
2308
 
                if (show) {
2309
 
                        DebugDialog::debug(QString("unrouted %1 %2 %3 %4")
2310
 
                                .arg(connectorItem->attachedToInstanceTitle())
2311
 
                                .arg(connectorItem->attachedToID())
2312
 
                                .arg(connectorItem->attachedTo()->title())
2313
 
                                .arg(connectorItem->connectorSharedName()));
2314
 
                }
2315
 
 
2316
 
                if (connectorItem->isActive() && connectorItem->isVisible() && !connectorItem->hidden()) {
2317
 
                        connectorItem->showEqualPotential(show);
2318
 
                }
2319
 
                else {
2320
 
                        connectorItem = connectorItem->getCrossLayerConnectorItem();
2321
 
                        if (connectorItem) connectorItem->showEqualPotential(show);
2322
 
                }
2323
 
        }
2324
 
}
2325
 
 
2326
 
void MainWindow::setReportMissingModules(bool b) {
2327
 
        if (m_sketchModel) {
2328
 
                m_sketchModel->setReportMissingModules(b);
2329
 
        }
2330
 
}
2331
 
 
2332
 
void MainWindow::warnSMD(const QString & moduleID) {
2333
 
 
2334
 
        ModelPart * mp = m_refModel->retrieveModelPart(moduleID);
2335
 
        if (mp == NULL) return;
2336
 
 
2337
 
        if (!mp->flippedSMD()) return;
2338
 
 
2339
 
        if (m_pcbGraphicsView->routeBothSides()) {
2340
 
                if (!m_pcbGraphicsView->layerIsActive(ViewLayer::Copper1)) {
2341
 
                        activeLayerBoth();
2342
 
                }
2343
 
                return;
2344
 
        }
2345
 
 
2346
 
        if (m_smdOneSideWarningGiven) return;
2347
 
 
2348
 
    int boardCount;
2349
 
        ItemBase * board = m_pcbGraphicsView->findSelectedBoard(boardCount);
2350
 
        if (board == NULL) return;
2351
 
 
2352
 
        m_smdOneSideWarningGiven = true;
2353
 
        // don't want to trigger the message box and subsequent swap from within the original event
2354
 
        QTimer::singleShot(15, this, SLOT(warnSMDReally()));
2355
 
}
2356
 
 
2357
 
void MainWindow::warnSMDReally() 
2358
 
{
2359
 
        QMessageBox messageBox(this);
2360
 
    messageBox.setWindowTitle(tr("Using SMD parts"));
2361
 
    messageBox.setInformativeText(tr("When using SMD parts, a double-sided board is usually desired. "
2362
 
                                                                        "On the default single-sided board, SMD parts will end up on the back of the board."));
2363
 
        messageBox.setText(tr("Do you want to swap to a double-sided board now?"));
2364
 
    messageBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
2365
 
    messageBox.setDefaultButton(QMessageBox::Yes);
2366
 
    messageBox.setIcon(QMessageBox::Information);
2367
 
    messageBox.setWindowModality(Qt::WindowModal);
2368
 
    messageBox.setButtonText(QMessageBox::Yes, tr("Swap"));
2369
 
    messageBox.setButtonText(QMessageBox::No, tr("Don't Swap"));
2370
 
    messageBox.button(QMessageBox::No)->setShortcut(tr("Ctrl+D"));
2371
 
 
2372
 
        int ret = messageBox.exec();
2373
 
        switch (ret) {
2374
 
                case QMessageBox::Yes:
2375
 
                        break;
2376
 
                default:
2377
 
                        return;
2378
 
        }
2379
 
 
2380
 
    int boardCount;
2381
 
        ItemBase * board = m_pcbGraphicsView->findSelectedBoard(boardCount);
2382
 
        swapLayers(board, 2, tr("Change to two layer pcb"), true, SketchWidget::PropChangeDelay);
2383
 
}
2384
 
 
2385
 
 
2386
 
void MainWindow::boardDeletedSlot() 
2387
 
{
2388
 
        activeLayerBottom();
2389
 
}
2390
 
 
2391
 
void MainWindow::cursorLocationSlot(double xinches, double yinches)
2392
 
{
2393
 
        if (m_locationLabel) {
2394
 
                QString units;
2395
 
                double x, y;
2396
 
 
2397
 
                m_locationLabel->setProperty("location", QSizeF(xinches, xinches));
2398
 
 
2399
 
                if (m_locationLabelUnits.compare("mm") == 0) {
2400
 
                        units = "mm";
2401
 
                        x = xinches * 25.4;
2402
 
                        y = yinches * 25.4;
2403
 
                }
2404
 
                else if (m_locationLabelUnits.compare("px") == 0) {
2405
 
                        units = "px";
2406
 
                        x = xinches * GraphicsUtils::SVGDPI;
2407
 
                        y = yinches * GraphicsUtils::SVGDPI;
2408
 
                }
2409
 
                else {
2410
 
                        units = "in";
2411
 
                        x = xinches;
2412
 
                        y = yinches;
2413
 
                }
2414
 
 
2415
 
                m_locationLabel->setText(tr("%1 %2 %3")
2416
 
                        .arg(x, 0, 'f', 3)
2417
 
                        .arg(y, 0, 'f', 3)
2418
 
                        .arg(units) );
2419
 
        }
2420
 
}
2421
 
 
2422
 
void MainWindow::locationLabelClicked()
2423
 
{
2424
 
        if (m_locationLabelUnits.compare("mm") == 0) {
2425
 
                m_locationLabelUnits = "px";
2426
 
        }
2427
 
        else if (m_locationLabelUnits.compare("px") == 0) {
2428
 
                m_locationLabelUnits = "in";
2429
 
        }
2430
 
        else if (m_locationLabelUnits.compare("in") == 0) {
2431
 
                m_locationLabelUnits = "mm";
2432
 
        }
2433
 
        else {
2434
 
                m_locationLabelUnits = "in";
2435
 
        }
2436
 
 
2437
 
        if (m_locationLabel) {
2438
 
                QVariant variant =  m_locationLabel->property("location");
2439
 
                if (variant.isValid()) {
2440
 
                        QSizeF size = variant.toSizeF();
2441
 
                        cursorLocationSlot(size.width(), size.height());
2442
 
                }
2443
 
                else {
2444
 
                        cursorLocationSlot(0, 0);
2445
 
                }
2446
 
        }
2447
 
                
2448
 
        QSettings settings;
2449
 
        settings.setValue("LocationInches", QVariant(m_locationLabelUnits));
2450
 
}
2451
 
 
2452
 
void MainWindow::filenameIfSlot(QString & filename)
2453
 
{
2454
 
        filename = QFileInfo(fileName()).fileName();
2455
 
}
2456
 
 
2457
 
QList<SketchWidget *> MainWindow::sketchWidgets() 
2458
 
{
2459
 
        QList<SketchWidget *> list;
2460
 
        list << m_breadboardGraphicsView << m_schematicGraphicsView << m_pcbGraphicsView;
2461
 
        return list;
2462
 
}
2463
 
 
2464
 
void MainWindow::setCloseSilently(bool cs)
2465
 
{
2466
 
        m_closeSilently = cs;
2467
 
}
2468
 
 
2469
 
PCBSketchWidget * MainWindow::pcbView() {
2470
 
        return m_pcbGraphicsView;
2471
 
}
2472
 
 
2473
 
void MainWindow::noBackup()
2474
 
{
2475
 
        m_autosaveTimer.stop();
2476
 
}
2477
 
 
2478
 
void MainWindow::hideTempPartsBin() {
2479
 
        if (m_binManager) m_binManager->hideTempPartsBin();
2480
 
}
2481
 
 
2482
 
void MainWindow::setActiveWire(Wire * wire) {
2483
 
        m_activeWire = wire;
2484
 
}
2485
 
 
2486
 
void MainWindow::setActiveConnectorItem(ConnectorItem * connectorItem) {
2487
 
        m_activeConnectorItem = connectorItem;
2488
 
}
2489
 
 
2490
 
const QString & MainWindow::fritzingVersion() {
2491
 
        if (m_sketchModel) return m_sketchModel->fritzingVersion();
2492
 
 
2493
 
        return ___emptyString___;
2494
 
}
2495
 
 
2496
 
 
2497
 
void MainWindow::dragEnterEvent(QDragEnterEvent *event)
2498
 
{
2499
 
    const QMimeData* mimeData = event->mimeData();
2500
 
 
2501
 
    if (mimeData->hasUrls()) {
2502
 
        QStringList pathList;
2503
 
        QList<QUrl> urlList = mimeData->urls();
2504
 
 
2505
 
        // extract the local paths of the files
2506
 
        for (int i = 0; i < urlList.size() && i < 32; ++i) {
2507
 
            QString fn = urlList.at(i).toLocalFile();
2508
 
            foreach (QString ext, fritzingExtensions()) {
2509
 
                if (fn.endsWith(ext)) {
2510
 
                    event->acceptProposedAction();
2511
 
                    return;
2512
 
                }
2513
 
            }
2514
 
        }
2515
 
    }
2516
 
}
2517
 
 
2518
 
void MainWindow::dropEvent(QDropEvent *event)
2519
 
{
2520
 
    const QMimeData* mimeData = event->mimeData();
2521
 
 
2522
 
    if (mimeData->hasUrls()) {
2523
 
        QStringList pathList;
2524
 
        QList<QUrl> urlList = mimeData->urls();
2525
 
 
2526
 
        // extract the local paths of the files
2527
 
        for (int i = 0; i < urlList.size() && i < 32; ++i) {
2528
 
            mainLoadAux(urlList.at(i).toLocalFile());
2529
 
        }
2530
 
    }
2531
 
}
2532
 
 
2533