Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

HackStudio: New project dialog + Project templates #5213

Merged
merged 2 commits into from Feb 13, 2021

Conversation

nvella
Copy link
Contributor

@nvella nvella commented Feb 1, 2021

Decided to get this up as a draft to get some running feedback as I work on it, commits aren't squashed yet All features done, rebased onto master and tested working - ready for a proper review 😃

Summary

New Project dialog for HackStudio which reads simple templates from /res/devel/templates. Templates consist of an INI file (template manifest,) at the moment containing just name and description texts, a directory containing the template contents, and optionally a post-creation script which is ran at create-time with the project name and path as arguments. Four templates are included; empty, C++ basic (command-line), C++ GUI (a simple Hello World example), and C++ shared library. Icons are stored in /res/icons/hackstudio/templates-32x32 and share the same name as the template manifest INI and content directory.

image

What's done

  • Dialog design and implementation
  • ProjectTemplate class and ProjectTemplateManager singleton class
  • ProjectTemplate::create_project method, where the magic happens.
  • Empty, basic C++ command-line and C++ GUI templates
  • C++ shared library template
  • Automatically opening project on creation

What I'm not entirely sure about

Still getting the hang of the general concept of smart pointers, I come from the land of managed memory (.NET) so go easy on me. 😅 There's probably a few mistakes around my pointer choices, object allocation methods and so on - constructive criticism is very much appreciated :)

Copy link
Member

@linusg linusg left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not a thorough review, just some feedback

Base/res/devel/templates/cpp-basic.ini Outdated Show resolved Hide resolved
Base/res/devel/templates/cpp-basic.ini Outdated Show resolved Hide resolved
Base/res/devel/templates/cpp-gui/main.cpp Outdated Show resolved Hide resolved
Userland/DevTools/HackStudio/CMakeLists.txt Outdated Show resolved Hide resolved
Userland/DevTools/HackStudio/ProjectTemplate.cpp Outdated Show resolved Hide resolved
@nvella nvella force-pushed the hackstudio-new-project branch 2 times, most recently from 5b1e90d to 4a712fe Compare February 7, 2021 07:13
@nvella nvella requested a review from linusg February 7, 2021 07:14
@nvella
Copy link
Contributor Author

nvella commented Feb 7, 2021

Feedback has been applied @linusg :) I've also since added a rudimentary shared library template, and we're also now automatically opening the project after successful creation.

@nvella nvella marked this pull request as ready for review February 7, 2021 07:21
Copy link
Contributor

@Dexesttp Dexesttp left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I really like this - very good feature for both newcomers and quick project creation, using the shell for postcreate scripts seem like it's going to be very versatile, and the UI is sleek !

Just a few feedbacks, I don't think any of them are blocking, though :)

Userland/DevTools/HackStudio/ProjectTemplateManager.h Outdated Show resolved Hide resolved
Userland/DevTools/HackStudio/ProjectTemplate.cpp Outdated Show resolved Hide resolved
Userland/DevTools/HackStudio/ProjectTemplate.cpp Outdated Show resolved Hide resolved
Comment on lines 234 to 241
if (project_template->create_project(maybe_project_name.value(), maybe_project_full_path.value())) {
// Succesfully created, attempt to open the new project
m_created_project_path = maybe_project_full_path.value();
done(ExecResult::ExecOK);
} else {
GUI::MessageBox::show_error(this, "Could not create project: internal error. Please check your parameters and try again.");
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about making project_template return an AK::Result<String, String> instead, with the first being the created project full path (for easier unwrapping below), and the second being a more detailed error string ? "Internal Error" is not as descriptive as we could be, and it seems like create_project could return a better message pretty easily.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I may very well be missing something obvious, but it seems it's impossible to specify an error value for a Result with the same value and error type, which stops us from passing through the unwrapped project full path. It is possible to construct a Result<void, String> however, still allowing us to pass through an error string. It doesn't seem to be much functionally differently from a Optional<string>, but it seems like a more explicit way to pass an error than just using an Optional.

Comment on lines +157 to +162
if (maybe_project_path.has_value()) {
m_full_path_label->set_text(maybe_project_path.value());
} else {
m_full_path_label->set_text("Invalid name or creation directory.");
m_input_valid = false;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as for the project template, having the project path be an Option<String> instead of a Result<String, String> limits the message we can show to the user ("Invalid" isn't as useful as we could be, given that the get_project_full_path() method can fail in 6 different ways both by itself or in get_available_project_name()).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Referring to the previous conversation, it seems I'll have to pass on this for now until I find out how to specify an error value for Results with the same value and error type 😄 Shouldn't be too much of a problem for now.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wow, that's right ! I hadn't even considered the possibility thiat it couldn't be done, and that seems like an unfortunate limitation of the Result type.
I don't have any issues with skipping it for this PR. It's just a small usability thing that can be improved later once the Result<T, T> thing is possible!

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

An alternative would be to have a :

struct TemplateCreationError {
    TemplateCreationError(String message)
        : message(message)
    {
    }
    String message;
}

and use it as the error type. This way, you could write return TemplateCreationError("My message");

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm... I've managed to pass along the template creation error with a Result<void, String> so far, do you think it would be more correct defining a specific error struct for this circumstance, even though only a String is being passed at the moment?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you hold on just a few minutes I'll push my new changes up (unsquashed) :)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't actually know if creating a specific struct for errors is good practice in C++.
@awesomekling thoughts about using Result<void, String> vs Result<void, TemplateCreationError>, where TemplateCreationError is a wrapper struct around a string ?

@awesomekling
Copy link
Member

Very cool work! Love this feature. ⭐
Please fix conflicts, and also remove the merge commit from the PR :)

@nvella
Copy link
Contributor Author

nvella commented Feb 10, 2021

Very cool work! Love this feature. ⭐

Please fix conflicts, and also remove the merge commit from the PR :)

No worries, and thanks for the review 😄 I'm usually quite busy during the week, I should be able to get around to all of it Friday evening (upside-down time 😆)

@nvella
Copy link
Contributor Author

nvella commented Feb 12, 2021

Just pushed my commits addressing the reviews :) Not yet squashed so it's a bit easier to distil my new changes, but otherwise will go ahead once all is OK Went ahead and squashed just then, as always I welcome any extra relevant feedback :)

In some circumstances (like template selection dialogs,) displaying as much
item label as possible, on all items, may be desired.

The default setting is 'false', which matches the default behaviour from before;
only wrapping on hover or selection.
This commit adds a simple project template system to HackStudio,
as well as a pretty New Project dialog, inspired by early VS.NET
and MS Office.
@awesomekling awesomekling merged commit b671577 into SerenityOS:master Feb 13, 2021
@nvella nvella deleted the hackstudio-new-project branch November 10, 2022 05:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants