FreeCAD

Форк
0
/
MDIView.cpp 
461 строка · 15.0 Кб
1
/***************************************************************************
2
 *   Copyright (c) 2007 Werner Mayer <wmayer[at]users.sourceforge.net>     *
3
 *                                                                         *
4
 *   This file is part of the FreeCAD CAx development system.              *
5
 *                                                                         *
6
 *   This library is free software; you can redistribute it and/or         *
7
 *   modify it under the terms of the GNU Library General Public           *
8
 *   License as published by the Free Software Foundation; either          *
9
 *   version 2 of the License, or (at your option) any later version.      *
10
 *                                                                         *
11
 *   This library  is distributed in the hope that it will be useful,      *
12
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
13
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
14
 *   GNU Library General Public License for more details.                  *
15
 *                                                                         *
16
 *   You should have received a copy of the GNU Library General Public     *
17
 *   License along with this library; see the file COPYING.LIB. If not,    *
18
 *   write to the Free Software Foundation, Inc., 59 Temple Place,         *
19
 *   Suite 330, Boston, MA  02111-1307, USA                                *
20
 *                                                                         *
21
 ***************************************************************************/
22

23
#include "PreCompiled.h"
24

25
#ifndef _PreComp_
26
# include <boost_signals2.hpp>
27
# include <boost/core/ignore_unused.hpp>
28
# include <QApplication>
29
# include <QEvent>
30
# include <QCloseEvent>
31
# include <QMdiSubWindow>
32
# include <QPrintDialog>
33
# include <QPrintPreviewDialog>
34
# include <QPrinter>
35
# include <QPrinterInfo>
36
# include <QRegularExpression>
37
# include <QRegularExpressionMatch>
38
#endif
39

40
#include <Base/Interpreter.h>
41
#include <App/Document.h>
42

43
#include "MDIView.h"
44
#include "MDIViewPy.h"
45
#include "Application.h"
46
#include "Document.h"
47
#include "FileDialog.h"
48
#include "MainWindow.h"
49
#include "ViewProviderDocumentObject.h"
50

51

52
using namespace Gui;
53
namespace sp = std::placeholders;
54

55
TYPESYSTEM_SOURCE_ABSTRACT(Gui::MDIView,Gui::BaseView)
56

57

58
MDIView::MDIView(Gui::Document* pcDocument,QWidget* parent, Qt::WindowFlags wflags)
59
  : QMainWindow(parent, wflags)
60
  , BaseView(pcDocument)
61
  , pythonObject(nullptr)
62
  , currentMode(Child)
63
  , wstate(Qt::WindowNoState)
64
  , ActiveObjects(pcDocument)
65
{
66
    setAttribute(Qt::WA_DeleteOnClose);
67

68
    if (pcDocument)
69
    {
70
      //NOLINTBEGIN
71
      connectDelObject = pcDocument->signalDeletedObject.connect
72
        (std::bind(&ActiveObjectList::objectDeleted, &ActiveObjects, sp::_1));
73
      assert(connectDelObject.connected());
74
      //NOLINTEND
75
    }
76
}
77

78
MDIView::~MDIView()
79
{
80
    //This view might be the focus widget of the main window. In this case we must
81
    //clear the focus and e.g. set the focus directly to the main window, otherwise
82
    //the application crashes when accessing this deleted view.
83
    //This effect only occurs if this widget is not in Child mode, because otherwise
84
    //the focus stuff is done correctly.
85
    if (getMainWindow()) {
86
        QWidget* foc = getMainWindow()->focusWidget();
87
        if (foc) {
88
            QWidget* par = foc;
89
            while (par) {
90
                if (par == this) {
91
                    getMainWindow()->setFocus();
92
                    break;
93
                }
94
                par = par->parentWidget();
95
            }
96
        }
97
    }
98
    if (connectDelObject.connected())
99
      connectDelObject.disconnect();
100

101
    if (pythonObject) {
102
        Base::PyGILStateLocker lock;
103
        Py_DECREF(pythonObject);
104
        pythonObject = nullptr;
105
    }
106
}
107

108
void MDIView::deleteSelf()
109
{
110
    // When using QMdiArea make sure to remove the QMdiSubWindow
111
    // this view is associated with.
112
    //
113
    // #0001023: Crash when quitting after using Windows > Tile
114
    // Use deleteLater() instead of delete operator.
115
    QWidget* parent = this->parentWidget();
116
    if (qobject_cast<QMdiSubWindow*>(parent)) {
117
        // https://forum.freecad.org/viewtopic.php?f=22&t=23070
118
        parent->close();
119
    }
120
    else {
121
        this->close();
122
    }
123

124
    // detach from document
125
    if (_pcDocument)
126
        onClose();
127
    _pcDocument = nullptr;
128
}
129

130
PyObject* MDIView::getPyObject()
131
{
132
    if (!pythonObject)
133
        pythonObject = new MDIViewPy(this);
134

135
    Py_INCREF(pythonObject);
136
    return pythonObject;
137
}
138

139
void MDIView::setOverrideCursor(const QCursor& c)
140
{
141
    Q_UNUSED(c);
142
}
143

144
void  MDIView::restoreOverrideCursor()
145
{
146
}
147

148
void MDIView::onRelabel(Gui::Document *pDoc)
149
{
150
    if (!bIsPassive) {
151
        // Try to separate document name and view number if there is one
152
        QString cap = windowTitle();
153
        // Either with dirty flag ...
154
        QRegularExpression rx(QLatin1String(R"((\s\:\s\d+\[\*\])$)"));
155
        QRegularExpressionMatch match;
156
        //int pos =
157
        boost::ignore_unused(cap.lastIndexOf(rx, -1, &match));
158
        if (!match.hasMatch()) {
159
            // ... or not
160
            rx.setPattern(QLatin1String(R"((\s\:\s\d+)$)"));
161
            //pos =
162
            boost::ignore_unused(cap.lastIndexOf(rx, -1, &match));
163
        }
164
        if (match.hasMatch()) {
165
            cap = QString::fromUtf8(pDoc->getDocument()->Label.getValue());
166
            cap += match.captured();
167
            setWindowTitle(cap);
168
        }
169
        else {
170
            cap = QString::fromUtf8(pDoc->getDocument()->Label.getValue());
171
            cap = QString::fromLatin1("%1[*]").arg(cap);
172
            setWindowTitle(cap);
173
        }
174
    }
175
}
176

177
void MDIView::viewAll()
178
{
179
}
180

181
/// receive a message
182
bool MDIView::onMsg(const char* pMsg,const char** ppReturn)
183
{
184
    Q_UNUSED(pMsg);
185
    Q_UNUSED(ppReturn);
186
    return false;
187
}
188

189
bool MDIView::onHasMsg(const char* pMsg) const
190
{
191
    Q_UNUSED(pMsg);
192
    return false;
193
}
194

195
bool MDIView::canClose()
196
{
197
    if (getAppDocument() && getAppDocument()->testStatus(App::Document::TempDoc))
198
        return true;
199

200
    if (!bIsPassive && getGuiDocument() && getGuiDocument()->isLastView()) {
201
        this->setFocus(); // raises the view to front
202
        return (getGuiDocument()->canClose(true,true));
203
    }
204

205
    return true;
206
}
207

208
void MDIView::closeEvent(QCloseEvent *e)
209
{
210
    if (canClose()) {
211
        e->accept();
212
        if (!bIsPassive) {
213
            // must be detached so that the last view can get asked
214
            Document* doc = this->getGuiDocument();
215
            if (doc && !doc->isLastView())
216
                doc->detachView(this);
217
        }
218

219
        // Note: When using QMdiArea we must not use removeWindow()
220
        // because otherwise the QMdiSubWindow will lose its parent
221
        // and thus the notification in QMdiSubWindow::closeEvent of
222
        // other mdi windows to get maximized if this window
223
        // is maximized will fail.
224
        // This odd behaviour is caused by the invocation of
225
        // d->mdiArea->removeSubWindow(parent) which we must let there
226
        // because otherwise other parts don't work as they should.
227
        QMainWindow::closeEvent(e);
228
    }
229
    else {
230
        e->ignore();
231
    }
232
}
233

234
void MDIView::windowStateChanged(QWidget* view)
235
{
236
    Q_UNUSED(view)
237
}
238

239
void MDIView::print(QPrinter* printer)
240
{
241
    Q_UNUSED(printer);
242
    std::cerr << "Printing not implemented for " << this->metaObject()->className() << std::endl;
243
}
244

245
void MDIView::print()
246
{
247
    QPrinter printer(QPrinter::ScreenResolution);
248
    printer.setFullPage(true);
249
    QPrintDialog dlg(&printer, this);
250
    if (dlg.exec() == QDialog::Accepted) {
251
        print(&printer);
252
    }
253
}
254

255
void MDIView::printPdf()
256
{
257
    QString filename = FileDialog::getSaveFileName(this, tr("Export PDF"), QString(),
258
        QString::fromLatin1("%1 (*.pdf)").arg(tr("PDF file")));
259
    if (!filename.isEmpty()) {
260
        QPrinter printer(QPrinter::ScreenResolution);
261
        // setPdfVersion sets the printied PDF Version to comply with PDF/A-1b, more details under: https://www.kdab.com/creating-pdfa-documents-qt/
262
        printer.setPdfVersion(QPagedPaintDevice::PdfVersion_A1b);
263
        printer.setOutputFormat(QPrinter::PdfFormat);
264
        printer.setOutputFileName(filename);
265
        print(&printer);
266
    }
267
}
268

269
void MDIView::printPreview()
270
{
271
    QPrinter printer(QPrinter::ScreenResolution);
272
    QPrintPreviewDialog dlg(&printer, this);
273
    connect(&dlg, &QPrintPreviewDialog::paintRequested,
274
            this, qOverload<QPrinter*>(&MDIView::print));
275
    dlg.exec();
276
}
277

278
void MDIView::savePrinterSettings(QPrinter* printer)
279
{
280
    auto hGrp = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/Printer");
281
    QString printerName = printer->printerName();
282
    if (printerName.isEmpty()) {
283
        // no printer defined
284
        return;
285
    }
286

287
    hGrp = hGrp->GetGroup(printerName.toUtf8());
288

289
    hGrp->SetInt("DefaultPageSize", printer->pageLayout().pageSize().id());
290
    hGrp->SetInt("DefaultPageOrientation", static_cast<int>(printer->pageLayout().orientation()));
291
    hGrp->SetInt("DefaultColorMode", static_cast<int>(printer->colorMode()));
292
}
293

294
void MDIView::restorePrinterSettings(QPrinter* printer)
295
{
296
    auto hGrp = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/Printer");
297
    QString printerName = printer->printerName();
298
    if (printerName.isEmpty()) {
299
        // no printer defined
300
        return;
301
    }
302

303
    hGrp = hGrp->GetGroup(printerName.toUtf8());
304

305
    QPrinterInfo info = QPrinterInfo::defaultPrinter();
306
    int initialDefaultPageSize = info.isNull() ? QPageSize::A4 : info.defaultPageSize().id();
307
    int defaultPageSize = hGrp->GetInt("DefaultPageSize", initialDefaultPageSize);
308
    int defaultPageOrientation = hGrp->GetInt("DefaultPageOrientation", QPageLayout::Portrait);
309
    int defaultColorMode = hGrp->GetInt("DefaultColorMode", QPrinter::ColorMode::Color);
310

311
    printer->setPageSize(QPageSize(static_cast<QPageSize::PageSizeId>(defaultPageSize)));
312
    printer->setPageOrientation(static_cast<QPageLayout::Orientation>(defaultPageOrientation));
313
    printer->setColorMode(static_cast<QPrinter::ColorMode>(defaultColorMode));
314
}
315

316
QStringList MDIView::undoActions() const
317
{
318
    QStringList actions;
319
    Gui::Document* doc = getGuiDocument();
320
    if (doc) {
321
        std::vector<std::string> vecUndos = doc->getUndoVector();
322
        for (const auto & vecUndo : vecUndos) {
323
            actions << QCoreApplication::translate("Command", vecUndo.c_str());
324
        }
325
    }
326

327
    return actions;
328
}
329

330
QStringList MDIView::redoActions() const
331
{
332
    QStringList actions;
333
    Gui::Document* doc = getGuiDocument();
334
    if (doc) {
335
        std::vector<std::string> vecRedos = doc->getRedoVector();
336
        for (const auto & vecRedo : vecRedos) {
337
            actions << QCoreApplication::translate("Command", vecRedo.c_str());
338
        }
339
    }
340

341
    return actions;
342
}
343

344
QSize MDIView::minimumSizeHint () const
345
{
346
    return {400, 300};
347
}
348

349
void MDIView::changeEvent(QEvent *e)
350
{
351
    switch (e->type()) {
352
        case QEvent::ActivationChange:
353
            {
354
                // Forces this top-level window to be the active view of the main window
355
                if (isActiveWindow()) {
356
                    if (getMainWindow()->activeWindow() != this)
357
                        getMainWindow()->setActiveWindow(this);
358
                }
359
            }   break;
360
        case QEvent::WindowTitleChange:
361
        case QEvent::ModifiedChange:
362
            {
363
                // sets the appropriate tab of the tabbar
364
                getMainWindow()->tabChanged(this);
365
            }   break;
366
        default:
367
            {
368
                QMainWindow::changeEvent(e);
369
            }   break;
370
    }
371
}
372

373
#if defined(Q_WS_X11)
374
// To fix bug #0000345 move function declaration to here
375
extern void qt_x11_wait_for_window_manager( QWidget* w ); // defined in qwidget_x11.cpp
376
#endif
377

378
void MDIView::setCurrentViewMode(ViewMode mode)
379
{
380
    switch (mode) {
381
        // go to normal mode
382
        case Child:
383
            {
384
                if (this->currentMode == FullScreen) {
385
                    showNormal();
386
                    setWindowFlags(windowFlags() & ~Qt::Window);
387
                }
388
                else if (this->currentMode == TopLevel) {
389
                    this->wstate = windowState();
390
                    setWindowFlags( windowFlags() & ~Qt::Window );
391
                }
392

393
                if (this->currentMode != Child) {
394
                    this->currentMode = Child;
395
                    getMainWindow()->addWindow(this);
396
                    getMainWindow()->activateWindow();
397
                    update();
398
                }
399
            }   break;
400
        // go to top-level mode
401
        case TopLevel:
402
            {
403
                if (this->currentMode == Child) {
404
                    if (qobject_cast<QMdiSubWindow*>(this->parentWidget()))
405
                        getMainWindow()->removeWindow(this,false);
406
                    setWindowFlags(windowFlags() | Qt::Window);
407
                    setParent(nullptr, Qt::Window | Qt::WindowTitleHint | Qt::WindowSystemMenuHint |
408
                                 Qt::WindowMinMaxButtonsHint);
409
                    if (this->wstate & Qt::WindowMaximized)
410
                        showMaximized();
411
                    else
412
                        showNormal();
413

414
#if defined(Q_WS_X11)
415
                    //extern void qt_x11_wait_for_window_manager( QWidget* w ); // defined in qwidget_x11.cpp
416
                    qt_x11_wait_for_window_manager(this);
417
#endif
418
                    activateWindow();
419
                }
420
                else if (this->currentMode == FullScreen) {
421
                    if (this->wstate & Qt::WindowMaximized)
422
                        showMaximized();
423
                    else
424
                        showNormal();
425
                }
426

427
                this->currentMode = TopLevel;
428
                update();
429
            }   break;
430
        // go to fullscreen mode
431
        case FullScreen:
432
            {
433
                if (this->currentMode == Child) {
434
                    if (qobject_cast<QMdiSubWindow*>(this->parentWidget()))
435
                        getMainWindow()->removeWindow(this,false);
436
                    setWindowFlags(windowFlags() | Qt::Window);
437
                    setParent(nullptr, Qt::Window);
438
                    showFullScreen();
439
                }
440
                else if (this->currentMode == TopLevel) {
441
                    this->wstate = windowState();
442
                    showFullScreen();
443
                }
444

445
                this->currentMode = FullScreen;
446
                update();
447
            }   break;
448
    }
449
}
450

451
QString MDIView::buildWindowTitle() const
452
{
453
    QString windowTitle;
454
    if (Gui::Document* document = getGuiDocument()) {
455
        windowTitle.append(QString::fromStdString(getAppDocument()->Label.getStrValue()));
456
    }
457

458
    return windowTitle;
459
}
460

461
#include "moc_MDIView.cpp"
462

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.