X-Git-Url: https://git.sur5r.net/?p=fstl;a=blobdiff_plain;f=src%2Fwindow.cpp;fp=src%2Fwindow.cpp;h=09d74eddad444f5fb811d500a570d901b85fb8c4;hp=0954b33eb92f46b2951f7330c50221dcfc8917fe;hb=9e9c2e84ac7826bfcaf00c5c0c770f64e16c4abf;hpb=1f2ac8b235365a672fad76a404ca8a2b6e79915b diff --git a/src/window.cpp b/src/window.cpp index 0954b33..09d74ed 100644 --- a/src/window.cpp +++ b/src/window.cpp @@ -1,6 +1,4 @@ #include -#include -#include #include "window.h" #include "canvas.h" @@ -15,8 +13,11 @@ Window::Window(QWidget *parent) : quit_action(new QAction("Quit", this)), perspective_action(new QAction("Perspective", this)), orthogonal_action(new QAction("Orthographic", this)), + shaded_action(new QAction("Shaded", this)), + wireframe_action(new QAction("Wireframe", this)), reload_action(new QAction("Reload", this)), autoreload_action(new QAction("Autoreload", this)), + save_screenshot_action(new QAction("Save Screenshot", this)), recent_files(new QMenu("Open recent", this)), recent_files_group(new QActionGroup(this)), recent_files_clear_action(new QAction("Clear recent files", this)), @@ -26,10 +27,14 @@ Window::Window(QWidget *parent) : setWindowTitle("fstl"); setAcceptDrops(true); - QGLFormat format; + QSurfaceFormat format; + format.setDepthBufferSize(24); + format.setStencilBufferSize(8); format.setVersion(2, 1); - format.setSampleBuffers(true); + format.setProfile(QSurfaceFormat::CoreProfile); + QSurfaceFormat::setDefaultFormat(format); + canvas = new Canvas(format, this); setCentralWidget(canvas); @@ -63,6 +68,10 @@ Window::Window(QWidget *parent) : QObject::connect(recent_files_group, &QActionGroup::triggered, this, &Window::on_load_recent); + save_screenshot_action->setCheckable(false); + QObject::connect(save_screenshot_action, &QAction::triggered, + this, &Window::on_save_screenshot); + rebuild_recent_files(); auto file_menu = menuBar()->addMenu("File"); @@ -71,6 +80,7 @@ Window::Window(QWidget *parent) : file_menu->addSeparator(); file_menu->addAction(reload_action); file_menu->addAction(autoreload_action); + file_menu->addAction(save_screenshot_action); file_menu->addAction(quit_action); auto view_menu = menuBar()->addMenu("View"); @@ -88,6 +98,20 @@ Window::Window(QWidget *parent) : QObject::connect(projections, &QActionGroup::triggered, this, &Window::on_projection); + auto draw_menu = view_menu->addMenu("Draw Mode"); + draw_menu->addAction(shaded_action); + draw_menu->addAction(wireframe_action); + auto drawModes = new QActionGroup(draw_menu); + for (auto p : {shaded_action, wireframe_action}) + { + drawModes->addAction(p); + p->setCheckable(true); + } + shaded_action->setChecked(true); + drawModes->setExclusive(true); + QObject::connect(drawModes, &QActionGroup::triggered, + this, &Window::on_drawMode); + auto help_menu = menuBar()->addMenu("Help"); help_menu->addAction(about_action); @@ -98,7 +122,7 @@ void Window::on_open() { QString filename = QFileDialog::getOpenFileName( this, "Load .stl file", QString(), "*.stl"); - if (not filename.isNull()) + if (!filename.isNull()) { load_stl(filename); } @@ -190,6 +214,18 @@ void Window::on_projection(QAction* proj) } } +void Window::on_drawMode(QAction* mode) +{ + if (mode == shaded_action) + { + canvas->draw_shaded(); + } + else + { + canvas->draw_wireframe(); + } +} + void Window::on_watched_change(const QString& filename) { if (autoreload_action->isChecked()) @@ -218,6 +254,45 @@ void Window::on_load_recent(QAction* a) load_stl(a->data().toString()); } +void Window::on_loaded(const QString& filename) +{ + current_file = filename; +} + +void Window::on_save_screenshot() +{ + const auto image = canvas->grabFramebuffer(); + auto file_name = QFileDialog::getSaveFileName( + this, + tr("Save Screenshot Image"), + QStandardPaths::standardLocations(QStandardPaths::StandardLocation::PicturesLocation).first(), + "Images (*.png *.jpg)"); + + auto get_file_extension = [](const std::string& file_name) -> std::string + { + const auto location = std::find(file_name.rbegin(), file_name.rend(), '.'); + if (location == file_name.rend()) + { + return ""; + } + + const auto index = std::distance(file_name.rbegin(), location); + return file_name.substr(file_name.size() - index); + }; + + const auto extension = get_file_extension(file_name.toStdString()); + if(extension.empty() || (extension != "png" && extension != "jpg")) + { + file_name.append(".png"); + } + + const auto save_ok = image.save(file_name); + if(!save_ok) + { + QMessageBox::warning(this, tr("Error Saving Image"), tr("Unable to save screen shot image.")); + } +} + void Window::rebuild_recent_files() { QSettings settings; @@ -290,6 +365,8 @@ bool Window::load_stl(const QString& filename, bool is_reload) this, &Window::setWindowTitle); connect(loader, &Loader::loaded_file, this, &Window::set_watched); + connect(loader, &Loader::loaded_file, + this, &Window::on_loaded); autoreload_action->setEnabled(true); reload_action->setEnabled(true); } @@ -312,3 +389,131 @@ void Window::dropEvent(QDropEvent *event) { load_stl(event->mimeData()->urls().front().toLocalFile()); } + +void Window::sorted_insert(QStringList& list, const QCollator& collator, const QString& value) +{ + int start = 0; + int end = list.size() - 1; + int index = 0; + while (start <= end){ + int mid = (start+end)/2; + if (list[mid] == value) { + return; + } + int compare = collator.compare(value, list[mid]); + if (compare < 0) { + end = mid-1; + index = mid; + } else { + start = mid+1; + index = start; + } + } + + list.insert(index, value); +} + +void Window::build_folder_file_list() +{ + QString current_folder_path = QFileInfo(current_file).absoluteDir().absolutePath(); + if (!lookup_folder_files.isEmpty()) + { + if (current_folder_path == lookup_folder) { + return; + } + + lookup_folder_files.clear(); + } + lookup_folder = current_folder_path; + + QCollator collator; + collator.setNumericMode(true); + + QDirIterator dirIterator(lookup_folder, QStringList() << "*.stl", QDir::Files | QDir::Readable | QDir::Hidden); + while (dirIterator.hasNext()) { + dirIterator.next(); + + QString name = dirIterator.fileName(); + sorted_insert(lookup_folder_files, collator, name); + } +} + +QPair Window::get_file_neighbors() +{ + if (current_file.isEmpty()) { + return QPair(QString::null, QString::null); + } + + build_folder_file_list(); + + QFileInfo fileInfo(current_file); + + QString current_dir = fileInfo.absoluteDir().absolutePath(); + QString current_name = fileInfo.fileName(); + + QString prev = QString::null; + QString next = QString::null; + + QListIterator fileIterator(lookup_folder_files); + while (fileIterator.hasNext()) { + QString name = fileIterator.next(); + + if (name == current_name) { + if (fileIterator.hasNext()) { + next = current_dir + QDir::separator() + fileIterator.next(); + } + break; + } + + prev = name; + } + + if (!prev.isEmpty()) { + prev.prepend(QDir::separator()); + prev.prepend(current_dir); + } + + return QPair(prev, next); +} + +bool Window::load_prev(void) +{ + QPair neighbors = get_file_neighbors(); + if (neighbors.first.isEmpty()) { + return false; + } + + return load_stl(neighbors.first); +} + +bool Window::load_next(void) +{ + QPair neighbors = get_file_neighbors(); + if (neighbors.second.isEmpty()) { + return false; + } + + return load_stl(neighbors.second); +} + +void Window::keyPressEvent(QKeyEvent* event) +{ + if (!open_action->isEnabled()) + { + QMainWindow::keyPressEvent(event); + return; + } + + if (event->key() == Qt::Key_Left) + { + load_prev(); + return; + } + else if (event->key() == Qt::Key_Right) + { + load_next(); + return; + } + + QMainWindow::keyPressEvent(event); +}