File indexing completed on 2024-04-28 07:39:37
0001 /*. 0002 SPDX-FileCopyrightText: 2007 Vladimir Kuznetsov <ks.vladimir@gmail.com> 0003 0004 SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #include "mainwindow.h" 0008 0009 #include "ui_configure_step_general.h" 0010 0011 #include "clipboard.h" 0012 #include "worldmodel.h" 0013 #include "worldscene.h" 0014 #include "worldbrowser.h" 0015 #include "propertiesbrowser.h" 0016 #include "infobrowser.h" 0017 #include "undobrowser.h" 0018 #include "itempalette.h" 0019 #include "settings.h" 0020 #include "unitscalc.h" 0021 0022 #include <stepcore/solver.h> 0023 #include <stepcore/collisionsolver.h> 0024 0025 #include <QAction> 0026 #include <QDir> 0027 #include <QFile> 0028 #include <QFileDialog> 0029 #include <QGraphicsView> 0030 #include <QIcon> 0031 #include <QItemSelectionModel> 0032 #include <QKeySequence> 0033 #include <QMenu> 0034 #include <QStandardPaths> 0035 #include <QStatusBar> 0036 #include <QTemporaryFile> 0037 0038 #include <kwidgetsaddons_version.h> 0039 #include <KActionCollection> 0040 #include <KConfig> 0041 #include <KConfigDialog> 0042 #include <KIO/CopyJob> 0043 #include <KIO/Job> 0044 #include <KIO/FileCopyJob> 0045 #include <KJobWidgets> 0046 #include <KLocalizedString> 0047 #include <KMessageBox> 0048 #include <KNSWidgets/Action> 0049 #include <KRecentFilesAction> 0050 #include <KStandardAction> 0051 0052 #include <QActionGroup> 0053 #include <cstdlib> 0054 #include <ctime> 0055 0056 MainWindow::MainWindow() 0057 { 0058 std::srand(time(nullptr)); 0059 0060 // Load UnitCalc at startup 0061 UnitsCalc::self(); 0062 0063 setObjectName(QStringLiteral("MainWindow")); 0064 0065 setCorner(Qt::TopLeftCorner, Qt::LeftDockWidgetArea); 0066 setCorner(Qt::BottomLeftCorner, Qt::LeftDockWidgetArea); 0067 setCorner(Qt::TopRightCorner, Qt::RightDockWidgetArea); 0068 setCorner(Qt::BottomRightCorner, Qt::RightDockWidgetArea); 0069 0070 worldModel = new WorldModel(this); 0071 worldModel->setActions(actionCollection()); 0072 0073 itemPalette = new ItemPalette(worldModel, this); 0074 itemPalette->setObjectName(QStringLiteral("itemPalette")); 0075 addDockWidget(Qt::LeftDockWidgetArea, itemPalette); 0076 0077 worldBrowser = new WorldBrowser(worldModel, this); 0078 worldBrowser->setObjectName(QStringLiteral("worldBrowser")); 0079 addDockWidget(Qt::RightDockWidgetArea, worldBrowser); 0080 0081 propertiesBrowser = new PropertiesBrowser(worldModel, this); 0082 propertiesBrowser->setObjectName(QStringLiteral("propertiesBrowser")); 0083 addDockWidget(Qt::RightDockWidgetArea, propertiesBrowser); 0084 0085 infoBrowser = new InfoBrowser(worldModel, this); 0086 infoBrowser->setObjectName(QStringLiteral("infoBrowser")); 0087 addDockWidget(Qt::RightDockWidgetArea, infoBrowser); 0088 0089 undoBrowser = new UndoBrowser(worldModel, this); 0090 undoBrowser->setObjectName(QStringLiteral("undoBrowser")); 0091 addDockWidget(Qt::RightDockWidgetArea, undoBrowser); 0092 0093 worldScene = new WorldScene(worldModel, this); 0094 worldGraphicsView = new WorldGraphicsView(worldScene, this); 0095 setCentralWidget(worldGraphicsView); 0096 0097 connect(worldModel, &WorldModel::simulationStopped, this, &MainWindow::simulationStopped); 0098 connect(worldModel->selectionModel(), &QItemSelectionModel::selectionChanged, 0099 this, &MainWindow::worldSelectionChanged); 0100 connect(itemPalette, &ItemPalette::beginAddItem, 0101 worldScene, &WorldScene::beginAddItem); 0102 connect(worldScene, &WorldScene::endAddItem, 0103 itemPalette, &ItemPalette::endAddItem); 0104 connect(worldScene, SIGNAL(linkActivated(QUrl)), 0105 infoBrowser, SLOT(openUrl(QUrl))); 0106 connect(worldScene, &WorldScene::endAddItem, 0107 this, &MainWindow::worldSelectionChanged); 0108 0109 0110 setupActions(); 0111 setupGUI(); 0112 statusBar()->show(); 0113 0114 newFile(); 0115 } 0116 0117 MainWindow::~MainWindow() 0118 { 0119 disconnect(worldModel->undoStack(), &QUndoStack::cleanChanged, this, &MainWindow::updateCaption); 0120 0121 KConfig* config = new KConfig(QStringLiteral("steprc")); 0122 actionRecentFiles->saveEntries(config->group("RecentFiles")); 0123 delete config; 0124 } 0125 0126 void MainWindow::setupActions() 0127 { 0128 /* File menu */ 0129 KStandardAction::openNew(this, SLOT(newFile()), actionCollection()); 0130 KStandardAction::open(this, SLOT(openFile()), actionCollection()); 0131 KStandardAction::save(this, SLOT(saveFile()), actionCollection()); 0132 KStandardAction::saveAs(this, SLOT(saveFileAs()), actionCollection()); 0133 KStandardAction::quit(this, SLOT(close()), actionCollection()); 0134 actionRecentFiles = KStandardAction::openRecent(this, SLOT(openFile(QUrl)), 0135 actionCollection()); 0136 0137 KConfig* config = new KConfig(QStringLiteral("steprc")); 0138 actionRecentFiles->loadEntries(config->group("RecentFiles")); 0139 delete config; 0140 0141 QAction * actionOpenTutorial = actionCollection()->add<QAction>( 0142 QStringLiteral("file_tutorial_open"), this, SLOT(openTutorial())); 0143 actionOpenTutorial->setText(i18n("&Open Tutorial...")); 0144 actionOpenTutorial->setIcon(QIcon::fromTheme(QStringLiteral("document-open"))); 0145 0146 QAction * actionOpenExample = actionCollection()->add<QAction>( 0147 QStringLiteral("file_example_open"), this, SLOT(openExample())); 0148 actionOpenExample->setText(i18n("&Open Example...")); 0149 actionOpenExample->setIcon(QIcon::fromTheme(QStringLiteral("document-open"))); 0150 0151 QAction * actionOpenLocalExample = actionCollection()->add<QAction>( 0152 QStringLiteral("file_example_openlocal"), this, SLOT(openLocalExample())); 0153 actionOpenLocalExample->setText(i18n("Open Down&loaded Example...")); 0154 actionOpenLocalExample->setIcon(QIcon::fromTheme(QStringLiteral("document-open"))); 0155 0156 QAction * actionUploadExample = actionCollection()->add<QAction>( 0157 QStringLiteral("file_example_upload"), this, SLOT(uploadExample())); 0158 actionUploadExample->setText(i18n("Share C&urrent Experiment...")); 0159 actionUploadExample->setIcon(QIcon::fromTheme(QStringLiteral("get-hot-new-stuff"))); 0160 0161 KNSWidgets::Action *actionDownloadExamples = new KNSWidgets::Action(i18n("&Download New Experiments..."), QStringLiteral("step.knsrc"), actionCollection()); 0162 actionCollection()->addAction(QStringLiteral("file_example_download"), actionDownloadExamples); 0163 0164 /* Edit menu */ 0165 actionRedo = KStandardAction::redo(worldModel->undoStack(), SLOT(redo()), actionCollection()); 0166 actionUndo = KStandardAction::undo(worldModel->undoStack(), SLOT(undo()), actionCollection()); 0167 actionRedo->setEnabled(false); actionUndo->setEnabled(false); 0168 actionRedo->setIconText(i18n("Redo")); actionUndo->setIconText(i18n("Undo")); 0169 connect(worldModel->undoStack(), &QUndoStack::canRedoChanged, actionRedo, &QAction::setEnabled); 0170 connect(worldModel->undoStack(), &QUndoStack::canUndoChanged, actionUndo, &QAction::setEnabled); 0171 connect(worldModel->undoStack(), &QUndoStack::cleanChanged, this, &MainWindow::updateCaption); 0172 connect(worldModel->undoStack(), &QUndoStack::undoTextChanged, 0173 this, &MainWindow::undoTextChanged); 0174 connect(worldModel->undoStack(), &QUndoStack::redoTextChanged, 0175 this, &MainWindow::redoTextChanged); 0176 0177 actionCut = KStandardAction::cut(worldModel, SLOT(cutSelectedItems()), 0178 actionCollection()); 0179 actionCopy = KStandardAction::copy(worldModel, SLOT(copySelectedItems()), 0180 actionCollection()); 0181 actionPaste = KStandardAction::paste(worldModel, SLOT(pasteItems()), 0182 actionCollection()); 0183 actionCut->setEnabled(false); 0184 actionCopy->setEnabled(false); 0185 actionPaste->setEnabled(worldModel->clipboard()->canPaste()); 0186 connect(worldModel->clipboard(), &Clipboard::canPasteChanged, 0187 actionPaste, &QAction::setEnabled); 0188 0189 actionDelete = actionCollection()->add<QAction>(QStringLiteral("edit_delete"), worldModel, SLOT(deleteSelectedItems())); 0190 actionDelete->setText(i18n("&Delete")); 0191 actionDelete->setIcon(QIcon::fromTheme(QStringLiteral("edit-delete"))); 0192 actionDelete->setEnabled(false); 0193 actionCollection()->setDefaultShortcut(actionDelete, QKeySequence(Qt::Key_Delete)); 0194 0195 /* Simulation menu */ 0196 // The run speed action group 0197 QActionGroup* runSpeedGroup = new QActionGroup(this); 0198 0199 // The run action collection, this is used in the toolbar to create a dropdown menu on the run button 0200 runSpeedAction = new QAction(QIcon::fromTheme(QStringLiteral("media-playback-start")), i18n("&Run"), this); 0201 connect(runSpeedAction, &QAction::triggered, 0202 this, &MainWindow::simulationStartStop); 0203 QMenu* runSpeedActionMenu = new QMenu(this); 0204 runSpeedAction->setMenu(runSpeedActionMenu); 0205 actionCollection()->addAction(QStringLiteral("run_speed"), runSpeedAction); 0206 runSpeedActionMenu->setStatusTip(i18n("Execute the program")); 0207 runSpeedActionMenu->setWhatsThis(i18n("Run: Execute the program")); 0208 0209 fullSpeedAct = new QAction(i18nc("@option:radio", "1x Speed"), this); 0210 actionCollection()->addAction(QStringLiteral("full_speed"), fullSpeedAct ); 0211 fullSpeedAct->setCheckable(true); 0212 fullSpeedAct->setChecked(true); 0213 connect(fullSpeedAct, &QAction::triggered, this, &MainWindow::setFullSpeed); 0214 runSpeedGroup->addAction(fullSpeedAct); 0215 runSpeedActionMenu->addAction(fullSpeedAct); 0216 0217 slowSpeedAct = new QAction(i18nc("@option:radio choose the slow speed", "2x Speed"), this); 0218 actionCollection()->addAction(QStringLiteral("slow_speed"), slowSpeedAct ); 0219 slowSpeedAct->setCheckable(true); 0220 connect(slowSpeedAct, &QAction::triggered, this, &MainWindow::setSlowSpeed); 0221 runSpeedGroup->addAction(slowSpeedAct); 0222 runSpeedActionMenu->addAction(slowSpeedAct); 0223 0224 slowerSpeedAct = new QAction(i18nc("@option:radio", "4x Speed"), this); 0225 actionCollection()->addAction(QStringLiteral("slower_speed"), slowerSpeedAct ); 0226 slowerSpeedAct->setCheckable(true); 0227 connect(slowerSpeedAct, &QAction::triggered, this, &MainWindow::setSlowerSpeed); 0228 runSpeedGroup->addAction(slowerSpeedAct); 0229 runSpeedActionMenu->addAction(slowerSpeedAct); 0230 0231 slowestSpeedAct = new QAction(i18nc("@option:radio", "8x Speed"), this); 0232 actionCollection()->addAction(QStringLiteral("slowest_speed"), slowestSpeedAct ); 0233 slowestSpeedAct->setCheckable(true); 0234 connect(slowestSpeedAct, &QAction::triggered, this, &MainWindow::setSlowestSpeed); 0235 runSpeedGroup->addAction(slowestSpeedAct); 0236 runSpeedActionMenu->addAction(slowestSpeedAct); 0237 0238 stepSpeedAct = new QAction(i18nc("@option:radio", "16x Speed"), this); 0239 actionCollection()->addAction(QStringLiteral("step_speed"), stepSpeedAct ); 0240 stepSpeedAct->setCheckable(true); 0241 connect(stepSpeedAct, &QAction::triggered, this, &MainWindow::setStepSpeed); 0242 runSpeedGroup->addAction(stepSpeedAct); 0243 runSpeedActionMenu->addAction(stepSpeedAct); 0244 0245 simulationStopped(0); 0246 0247 /* View menu */ 0248 KStandardAction::actualSize(worldGraphicsView, SLOT(actualSize()), actionCollection()); 0249 KStandardAction::fitToPage(worldGraphicsView, SLOT(fitToPage()), actionCollection()); 0250 KStandardAction::zoomIn(worldGraphicsView, SLOT(zoomIn()), actionCollection()); 0251 KStandardAction::zoomOut(worldGraphicsView, SLOT(zoomOut()), actionCollection()); 0252 0253 /* Settings menu */ 0254 KStandardAction::preferences(this, SLOT(configureStep()), actionCollection()); 0255 0256 /* Dock widgets */ 0257 actionCollection()->addAction(QStringLiteral("toggle_palette_dock"), itemPalette->toggleViewAction()); 0258 actionCollection()->addAction(QStringLiteral("toggle_world_dock"), worldBrowser->toggleViewAction()); 0259 actionCollection()->addAction(QStringLiteral("toggle_properties_dock"), propertiesBrowser->toggleViewAction()); 0260 actionCollection()->addAction(QStringLiteral("toggle_info_dock"), infoBrowser->toggleViewAction()); 0261 actionCollection()->addAction(QStringLiteral("toggle_undo_dock"), undoBrowser->toggleViewAction()); 0262 } 0263 0264 void MainWindow::updateCaption() 0265 { 0266 QString shownName; 0267 if (currentFileUrl.isEmpty()) 0268 shownName = i18nc("filename", "untitled.step"); //Fixme if needed 0269 else 0270 shownName = currentFileUrl.url(QUrl::PreferLocalFile); //QFileInfo(currentFileName).fileName(); 0271 setCaption(shownName, !worldModel->undoStack()->isClean()); 0272 } 0273 0274 bool MainWindow::queryClose() 0275 { 0276 if(worldModel->isSimulationActive()) simulationStop(); 0277 if(maybeSave()) { 0278 return true; 0279 } else { 0280 return false; 0281 } 0282 } 0283 0284 bool MainWindow::newFile() 0285 { 0286 if(worldModel->isSimulationActive()) simulationStop(); 0287 if(!maybeSave()) return false; 0288 0289 worldModel->clearWorld(); 0290 worldGraphicsView->actualSize(); 0291 worldGraphicsView->centerOn(0,0); 0292 currentFileUrl = QUrl(); 0293 updateCaption(); 0294 undoBrowser->setEmptyLabel(i18n("<new file>")); 0295 undoBrowser->setCurrentFileUrl(currentFileUrl); 0296 0297 setFullSpeed(); // resetting the speed to the default speed of 1x 0298 return true; 0299 } 0300 0301 bool MainWindow::openFile(const QUrl& url, const QUrl& startUrl) 0302 { 0303 if(worldModel->isSimulationActive()) simulationStop(); 0304 if(!maybeSave()) return false; 0305 0306 QUrl fileUrl = url; 0307 if(fileUrl.isEmpty()) { 0308 fileUrl = QFileDialog::getOpenFileUrl(this, i18nc("@title:window", "Open Step File"), startUrl, i18n("Step files (*.step)")); 0309 if(fileUrl.isEmpty()) return false; 0310 } 0311 0312 worldModel->clearWorld(); 0313 newFile(); 0314 0315 QFile file(fileUrl.path()); 0316 0317 if(!file.open(QIODevice::ReadOnly | QIODevice::Text)) { 0318 KMessageBox::error(this, i18n("Cannot open file '%1'", file.fileName())); 0319 return false; 0320 } 0321 0322 if(!worldModel->loadXml(&file)) { 0323 KMessageBox::error(this, i18n("Cannot parse file '%1': %2", fileUrl.url(QUrl::PreferLocalFile), 0324 worldModel->errorString())); 0325 return false; 0326 } 0327 0328 worldGraphicsView->fitToPage(); 0329 currentFileUrl = fileUrl; 0330 updateCaption(); 0331 actionRecentFiles->addUrl(fileUrl); 0332 undoBrowser->setEmptyLabel(i18n("<open file: %1>", fileUrl.fileName())); 0333 undoBrowser->setCurrentFileUrl(currentFileUrl); 0334 0335 return true; 0336 } 0337 0338 bool MainWindow::saveFileAs(const QUrl& url, const QUrl& startUrl) 0339 { 0340 if(worldModel->isSimulationActive()) simulationStop(); 0341 QUrl fileUrl = url; 0342 if(fileUrl.isEmpty()) { 0343 fileUrl = QFileDialog::getSaveFileUrl(this, i18nc("@title:window", "Save Step File"), startUrl.isEmpty() ? currentFileUrl : startUrl, i18n("Step files (*.step)")); 0344 if(fileUrl.isEmpty()) return false; 0345 } 0346 0347 bool local = fileUrl.isLocalFile(); 0348 QFile* file; 0349 0350 if(!local) { 0351 QTemporaryFile *tempFile = new QTemporaryFile(); 0352 tempFile->setAutoRemove(true); 0353 file = tempFile; 0354 } else { 0355 file = new QFile(fileUrl.path()); 0356 } 0357 0358 if(!file->open(QIODevice::WriteOnly | QIODevice::Text)) { 0359 KMessageBox::error(this, i18n("Cannot open file '%1'", file->fileName())); 0360 delete file; 0361 return false; 0362 } 0363 0364 if(!worldModel->saveXml(file)) { 0365 KMessageBox::error(this, i18n("Cannot save file '%1': %2", 0366 fileUrl.url(QUrl::PreferLocalFile), 0367 worldModel->errorString())); 0368 delete file; 0369 return false; 0370 } 0371 0372 if(!local) { 0373 KIO::FileCopyJob *job = KIO::file_copy(QUrl::fromLocalFile(file->fileName()), fileUrl, -1, KIO::Overwrite); 0374 KJobWidgets::setWindow(job, this); 0375 job->exec(); 0376 if (job->error()) { 0377 KMessageBox::error(this, job->errorString()); 0378 delete file; 0379 return false; 0380 } 0381 } 0382 0383 delete file; 0384 0385 worldModel->undoStack()->setClean(); 0386 currentFileUrl = fileUrl; 0387 updateCaption(); 0388 undoBrowser->setCurrentFileUrl(currentFileUrl); 0389 return true; 0390 } 0391 0392 bool MainWindow::saveFile() 0393 { 0394 if(worldModel->isSimulationActive()) simulationStop(); 0395 return saveFileAs(currentFileUrl); 0396 } 0397 0398 bool MainWindow::maybeSave() 0399 { 0400 if(!worldModel->undoStack()->isClean()) { 0401 #if KWIDGETSADDONS_VERSION >= QT_VERSION_CHECK(5, 100, 0) 0402 int ret = KMessageBox::warningTwoActionsCancel(this, 0403 #else 0404 int ret = KMessageBox::warningYesNoCancel(this, 0405 #endif 0406 i18n("The experiment has been modified.\nDo you want to save your changes?"), 0407 i18n("Warning - Step"), KStandardGuiItem::save(), KStandardGuiItem::discard()); 0408 #if KWIDGETSADDONS_VERSION >= QT_VERSION_CHECK(5, 100, 0) 0409 if (ret == KMessageBox::PrimaryAction) return saveFile(); 0410 #else 0411 if (ret == KMessageBox::Yes) return saveFile(); 0412 #endif 0413 else if(ret == KMessageBox::Cancel) return false; 0414 } 0415 return true; 0416 } 0417 0418 void MainWindow::openTutorial() 0419 { 0420 // XXX: need to be redone 0421 //qDebug() << "inside MainWindow::openTutorial()"; 0422 QStringList dirs = QStandardPaths::locateAll(QStandardPaths::AppLocalDataLocation, QStringLiteral("tutorials"), QStandardPaths::LocateDirectory); 0423 QString localDir = QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation) + QLatin1Char('/'); 0424 foreach(const QString &dirName, dirs) { 0425 //qDebug() << "dirName: " << dirName; 0426 if(!dirName.startsWith(localDir)) { 0427 openFile(QUrl(), QUrl::fromLocalFile(dirName)); 0428 return; 0429 } 0430 } 0431 } 0432 0433 void MainWindow::openExample() 0434 { 0435 //qDebug() << "inside MainWindow::openExample()"; 0436 // XXX: need to be redone 0437 QStringList dirs = QStandardPaths::locateAll(QStandardPaths::AppLocalDataLocation, QStringLiteral("examples"), QStandardPaths::LocateDirectory); 0438 QString localDir = QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation) + QLatin1Char('/'); 0439 foreach(const QString &dirName, dirs) { 0440 if(!dirName.startsWith(localDir)) { 0441 openFile(QUrl(), QUrl::fromLocalFile(dirName)); 0442 return; 0443 } 0444 } 0445 } 0446 0447 void MainWindow::openLocalExample() 0448 { 0449 // XXX: need to be redone 0450 QString dir = QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation) + "/examples"; 0451 if(dir.isEmpty()) return; 0452 QDir::root().mkpath(dir); 0453 openFile(QUrl(), QUrl::fromLocalFile(dir)); 0454 } 0455 0456 void MainWindow::uploadExample() 0457 { 0458 KMessageBox::error(this, i18n("Uploading is still not implemented in kdelibs."), 0459 i18n("Sorry - Step")); 0460 /* 0461 int ret = KMessageBox::questionYesNo(this, 0462 i18n("Do you want to upload current experiment to public web server ?"), 0463 i18n("Question - Step")); 0464 if(ret != KMessageBox::Yes) return; 0465 0466 if(currentFileUrl.isEmpty() || !worldModel->undoStack()->isClean()) { 0467 ret = KMessageBox::warningContinueCancel(this, 0468 i18n("The experiment is not saved. You should it before uploading."), 0469 i18n("Warning - Step"), KStandardGuiItem::save(), KStandardGuiItem::cancel()); 0470 if(ret != KMessageBox::Continue) return; 0471 if(!saveFile()) return; 0472 } 0473 0474 KNS::Engine::upload( currentFileUrl.url() ); 0475 */ 0476 } 0477 0478 void MainWindow::simulationStartStop() 0479 { 0480 if(worldModel->isSimulationActive()) simulationStop(); 0481 else simulationStart(); 0482 } 0483 0484 void MainWindow::simulationStart() 0485 { 0486 runSpeedAction->setIconText(i18n("&Stop")); 0487 runSpeedAction->setIcon(QIcon::fromTheme(QStringLiteral("media-playback-stop"))); 0488 0489 undoBrowser->setUndoEnabled(false); 0490 actionUndo->setEnabled(false); 0491 worldModel->simulationStart(); 0492 } 0493 0494 void MainWindow::simulationStopped(int result) 0495 { 0496 runSpeedAction->setIconText(i18n("&Simulate")); 0497 runSpeedAction->setIcon(QIcon::fromTheme(QStringLiteral("media-playback-start"))); 0498 0499 undoBrowser->setUndoEnabled(true); 0500 if(result == StepCore::Solver::ToleranceError) { 0501 KMessageBox::error(this, i18n("Cannot finish this step because local error " 0502 "is greater than local tolerance.\n" 0503 "Please check solver settings and try again.")); 0504 } else if(result == StepCore::Solver::IntersectionDetected || 0505 result == StepCore::Solver::CollisionDetected) { 0506 KMessageBox::error(this, i18n("Cannot finish this step because there are collisions " 0507 "which cannot be resolved automatically.\n" 0508 "Please move colliding objects apart and try again.")); 0509 } else if(result != StepCore::Solver::OK) { 0510 KMessageBox::error(this, i18n("Cannot finish this step because of an unknown error.")); 0511 } 0512 } 0513 0514 void MainWindow::simulationStop() 0515 { 0516 worldModel->simulationStop(); 0517 } 0518 0519 void MainWindow::setRunSpeed(int speed) 0520 { 0521 switch (speed) { 0522 case 0: fullSpeedAct->setChecked(true); 0523 worldModel->world()->setTimeScale( 1.0); 0524 break; 0525 case 1: slowSpeedAct->setChecked(true); 0526 worldModel->world()->setTimeScale( 2.0); 0527 break; 0528 case 2: slowerSpeedAct->setChecked(true); 0529 worldModel->world()->setTimeScale( 4.0); 0530 break; 0531 case 3: slowestSpeedAct->setChecked(true); 0532 worldModel->world()->setTimeScale( 8.0); 0533 break; 0534 case 4: stepSpeedAct->setChecked(true); 0535 worldModel->world()->setTimeScale( 16.0); 0536 break; 0537 } 0538 runSpeed = speed; 0539 } 0540 0541 void MainWindow::undoTextChanged(const QString& undoText) 0542 { 0543 if(undoText.isEmpty()) actionUndo->setText(i18n("&Undo")); 0544 else actionUndo->setText(i18n("&Undo: %1", undoText)); 0545 } 0546 0547 void MainWindow::redoTextChanged(const QString& redoText) 0548 { 0549 if(redoText.isEmpty()) actionRedo->setText(i18n("Re&do")); 0550 else actionRedo->setText(i18n("Re&do: %1", redoText)); 0551 } 0552 0553 void MainWindow::worldSelectionChanged() 0554 { 0555 if (!worldScene->hasItemCreator()) { 0556 foreach (const QModelIndex &index, 0557 worldModel->selectionModel()->selection().indexes()) { 0558 if (index != worldModel->worldIndex() && worldModel->item(index)) { 0559 actionDelete->setEnabled(true); 0560 actionCut->setEnabled(true); 0561 actionCopy->setEnabled(true); 0562 return; 0563 } 0564 } 0565 } 0566 actionDelete->setEnabled(false); 0567 actionCut->setEnabled(false); 0568 actionCopy->setEnabled(false); 0569 } 0570 0571 void MainWindow::configureStep() 0572 { 0573 if(KConfigDialog::showDialog( QStringLiteral("settings") )) return; 0574 0575 KConfigDialog* dialog = new KConfigDialog(this, QStringLiteral("settings"), Settings::self()); 0576 0577 Ui::ConfigureStepGeneralWidget generalUi; 0578 QWidget* generalWidget = new QWidget(nullptr); 0579 generalWidget->setObjectName(QStringLiteral("general")); 0580 generalUi.setupUi(generalWidget); 0581 dialog->addPage(generalWidget, i18n("General"), QStringLiteral("step")); //shows the "step" icon, the "general" icon doesn't exist 0582 0583 connect(dialog, &KConfigDialog::settingsChanged, 0584 worldGraphicsView, &WorldGraphicsView::settingsChanged); 0585 connect(dialog, &KConfigDialog::settingsChanged, 0586 propertiesBrowser, &PropertiesBrowser::settingsChanged); 0587 0588 dialog->show(); 0589 } 0590 0591 /* 0592 void MainWindow::on_actionNew_triggered(bool checked) 0593 { 0594 if(maybeSave()) newFile(); 0595 } 0596 0597 void MainWindow::on_actionOpen_triggered(bool checked) 0598 { 0599 if(maybeSave()) openFile(QString()); 0600 } 0601 0602 void MainWindow::on_actionSave_triggered(bool checked) 0603 { 0604 saveFileAs(currentFileName); 0605 } 0606 0607 void MainWindow::on_actionSaveAs_triggered(bool checked) 0608 { 0609 saveFile(); 0610 } 0611 0612 void MainWindow::on_actionStep_triggered(bool checked) 0613 { 0614 if(!worldModel->doWorldEvolve(0.1)) 0615 QMessageBox::warning(this, i18n("Step"), // XXX: retrieve error message from solver ! 0616 i18n("Cannot finish this step because local error is bigger than local tolerance.<br />" 0617 "Please check solver settings and try again.")); 0618 } 0619 0620 void MainWindow::on_actionSimulation_triggered(bool checked) 0621 { 0622 if(!simulationTimer->isActive()) { 0623 actionSimulation->setText(i18n("&Stop")); 0624 simulationTimer->start(); 0625 } else { 0626 simulationTimer->stop(); 0627 actionSimulation->setText(i18n("&Simulation")); 0628 } 0629 } 0630 0631 void MainWindow::on_simulationTimer_timeout() 0632 { 0633 worldModel->doWorldEvolve(1.0/FPS); 0634 } 0635 0636 void MainWindow::on_actionAboutStep_triggered(bool checked) 0637 { 0638 QMessageBox::about(this, i18n("About Step"), 0639 i18n("<center>The <b>Step</b> is an interactive physical simulator.<br /><br />" 0640 "Distributed under terms of the GNU GPL license.<br />" 0641 "(C) 2006-2007 Kuznetsov Vladimir.</center>")); 0642 } 0643 */ 0644 0645 #include "moc_mainwindow.cpp"