The editor now draws a grid showing the pixels if you are zoomed
in enough. Currently the threshold is a scale of 15 (so if one
pixel side on the image takes up > 15 pixels in the editor)
Previously we unveiled the file specified through the command-line
interface. Now, we just make the request through the
FileSystemAccessServer instead.
Previously we unveiled the file specified through the command-line
interface. Now, we just make the request through the
FileSystemAccessServer instead.
This check was fine earlier when we had access to the full filesystem,
but now that we are moving away from applications having unveiled
access to the filesystem, this check would just get rejected from
the kernel. This is rare / fast enough that performance should not
really matter in any case.
This is a feature I missed from Photoshop: it sets the scale and
position so that the image fits (it's longest dimension) into
the editor view. There's a 5% border left around the image to
provide context. This is just arbitrary seemed like the right
amount after some trial and error.
Previously EraseTool would only let you have hard lines, similar
to PenTool. After inheriting from BrushTool in previous commits,
making the eraser (optionally) behave like a brush is much easier.
We only need to change how the colors are handled for the hardness,
which is why the `draw_point()` call is a bit more involved. Just
blending the colors doesn't work here since we actually want to
replace the previous color, unlike in BrushTool where we are just
layering the color on top.
This removes all the code to handle events that was essentially
duplicated from BrushTool anyway :^)
I've also renamed "thickness"->"size" to have consistent
terminology.
Most of the logic implemented in PenTool was the same as BrushTool
anyway, with the only difference being how the actual lines were
drawn at the end. We now just override the `draw_line()` and
`draw_point()` methods instead.
We don't strictly need to override `draw_line()` here, but that
would just result in repeated calls to `draw_point()`, which is
wasteful.
Also renamed "thickness"->"size" to have consistent terminology.
The BrushTool is very cool, but it doesn't allow us to re-use any
of the code in other classes. Many of the other tools have duplicated
code for handling mouse events / keeping track of previous location,
etc.
This commit sets up BrushTool so that other tools can inherit from
it and override some virtual functions to allow similar behavior
without re-writing the code to keep track of mouse positions, etc.
In particular, we add public setters/getters for `size` and
`hardness` properties, and make `draw_point()` and `draw_line()`
virtual so that derived classes can override them.
Note: We still pass in `color` as a parameter for `draw_line()` and
`draw_point()` instead of using `color_for()` directly because it
doesn't really make sense to be constantly asking the ImageEditor
for the color when it's not really changing (for instance along all
the points of a line)
Sometimes you want to draw a straight line between 2 points, but
using the nice-looking brush we have instead of the hard line we
would get using the LineTool.
This patch adds the ability to click somewhere with the brush, and
then Shift+click somewhere else to draw a line between the two
points using the brush stroke. Seems like an obvious addition
considering we already have a helper function to draw lines :^)
The BFS implementation for BucketTool's flood-fill had sitations
which could result in infinite loop, causing OOM crashes due to
the queue growing unbounded. The way to fix this is to keep track
of the pixels we have already visited in the flood-fill algorithm
and ignore those if we ever encounter them again.
This also fixes the crashing issue from #9003. We still need a
better way to account for transparency, but that is beyond the scope
of this commit, and this issue still exists without any transparent
pixels.
This will restrict 3DFileViewer's access to the file system.
3DFileViewer loads a texture based on the path of the model loaded, this
will request access to the texture file before loading.
Previously, Assistant was able to re-execute itself due to a quirk in
the global cursor tracking logic, it seems.
Now it has become necessary to explicitly drop the lockfile before
activating the new Assistant instance.
Alternatively, this has always been a latent bug that only now has
become more likely.
Showing the position only with an active tool seems a bit confusing,
if you've opened up an image just to find out the coordinates of
a pixel for instance, there shouldn't be a need to have to select
a tool first.
Previously, we were ignoring the scale of the editor in the second
paint step. If you were zoomed in, the size while you were drawing
was not the same as the size of the final shape.
Previously, we were ignoring the scale of the editor in the second
paint step. If you were zoomed in, the size while you were drawing
was not the same as the size of the final shape.
Previously, we were ignoring the scale of the editor in the second
paint step. If you were zoomed in, the size while you were drawing
was not the same as the size of the final shape.
A previous commit I made broke layer dragging since the hole_index
was always being computed with respect to the top of the layer list
widget, however we were now drawing layers from the bottom. When
you didn't have enough layers to fill up the full height, dragging
them around would be weird.
This patch computes the hole index correctly using the same offset
we start drawing from, and fixes the behavior.
In addition to adding the action, this commit also makes the
`did_change_rect()` method take in an optional rect, which
represents the new rect position. By default it is the same as
`rect()`.
When we are cropping an image, we don't want to move the whole
cropped section to the top-left of the original image in the
ImageEditor widget, so this allows us to keep the cropped image's
position fixed.
With this patch, we now initialize the `WebContentConsoleClient` as soon
as the Page has loaded, instead of waiting for the Console Window to be
shown. This finally lets us see log messages that happened before the
window was opened! :^)
However, it is not perfect. Waiting until the page has loaded means we
lose any messages that happen *during* page load. Ideally we would
initialize the WCCC when the page *starts* loading instead, but it
requires that the page has a document and interpreter assigned and
accessible. As far as I can tell with my limited knowledge, this is not
the case until the page has completed loading.
The console widget now requests messages and receives them in bulk,
using the shiny new IPC calls. This lets it display console messages
that occurred before the widget was created. :^)
Previously, it would keep a pointer to the interpreter of the previous
page, which resulted in Crashy Fun Times.
This also changes the clearing behavior - instead of clearing the
console output every time the window is shown, we clear it when the page
changes. This is more useful, since before you would lose any log
messages that had happened before opening the window.
Having the BrowserWindow assigning Tab's internals felt a bit wrong.
This is also a step towards removing BrowserWindow as a friend class.
While I was at it, changed the Tab to having a pointer to the
ConsoleWidget instead of the Window, since that is usually what we want
to use, and it's awkward having to static_cast the main-widget
repeatedly.
When using a dark theme the name of the key does not show up well at
all. This is due to it being set with pallete().button_text(), which for
dark themes is a light color. As Keyboard Mapper does not follow the
system color theme, the text on the keys should not either.
Previously we would loop over all glyphs in the GlyphMap, compute
their rects, and then test to see if the mouse click position was
inside that rect. This is silly since each element in the glyph
map for a particular font is the same size, and we can just do
some coordinate manipulation to get the index directly.
We can now drag-and-drop files onto PixelPaint to be able to open
them. Each dropped file opens in a separate editor (which is the
default behavior of Photoshop).
Previously, all the UI setup was done in `main.cpp`, with a whole
bunch of lambdas,, and actions etc just being stored in the main
function. This is probably an artifact from back when it was first
created.
Most other applications now have a "MainWidget" class of some sort
which handles setting up all the UI/menubars, etc. More importantly,,
it also lets us handle application-wide events which we were
previously not able to do directly, since the main widget was just
a default GUI::Widget.
This patch moves all the core functionality of the PixelPaint
application into PixelPaint::MainWidget, which is then instantiated
by the main function. There is likely some more refactoring that
would help, but this commit is big enough as it is doing mostly
a direct port.
freq_bin was converted to double after it was calculated, so there was
a much higher probability it could be 0 instead of some comma number,
which meant that the bars always stayed on top.
The freq_bin in bins_per_group was multiplied only to be divided later,
which could even result in a crash if you set higher buffer size
(like 1000ms) in PlaybackManager, due to rounding errors I presume.
Casting u64 to float is probably not a safe thing to do. Also, keep
time deltas in u64 values as they can easily wrap between calculations.
This fixes CPU usage calculation when a process is spinning in a loop.
Prior this change, opening a playlist always spawned a new widget.
This could end up with having a few the same widgets, which you couldn't
even close (besides the last one).
The fd would get closed when the File went out of scope, so we couldn't
open any file specified by 'pp <path to file>'. We need the fd to be
alive and we solemnly swear to take good care of it and close it
ourselves later.
Previously all memory values on the performance was formatted as KiB,
but with such formatting it can be quite hard to read large numbers
(as mentioned by Andreas on todays office hours livestream :^)).
This patch makes use of the human readable formatting utilies and
displays them in an easier to read format.
Every tool that has a slider now registers the primary/secondary
sliders and now uses the same keyboard shortcuts to modify the
primary and secondary properties. `[` and `]` for the primary,
`{` and `}` for the secondary.
There are quite a few tools that might want to change certain values
based on consistent keyboard shortcuts. This commit allows tools to
hook up a "primary" and "secondary" slider with the base `Tool`
class, which can then handle updating those sliders with the common
shortcuts.
Note that any derived classes that want to override the `on_keydown`
function will manually need to call `Tool::on_keydown()`.
This new class will open and parse files (either images directly or .pp
project files) and one can get the parsed Image as well as other
information from it.
This patch removes a bunch of 'try_create_from..." methods from Image in
favor of using the ProjectLoader.
The only json_metadata that is available are Guides for now.
The ImageEditor knows more about the image than Image itself. So to save
a project with all the information known to the program about an image
it's logical that ImageEditor performs that task rather than the Image.
There isn't any additional data added yet, but now there's the
possibility to do so.
Our existing implementation did not check the element type of the other
pointer in the constructors and move assignment operators. This meant
that some operations that would require explicit casting on raw pointers
were done implicitly, such as:
- downcasting a base class to a derived class (e.g. `Kernel::Inode` =>
`Kernel::ProcFSDirectoryInode` in Kernel/ProcFS.cpp),
- casting to an unrelated type (e.g. `Promise<bool>` => `Promise<Empty>`
in LibIMAP/Client.cpp)
This, of course, allows gross violations of the type system, and makes
the need to type-check less obvious before downcasting. Luckily, while
adding the `static_ptr_cast`s, only two truly incorrect usages were
found; in the other instances, our casts just needed to be made
explicit.
And also try_create<T> => try_make_ref_counted<T>.
A global "create" was a bit much. The new name matches make<T> better,
which we've used for making single-owner objects since forever.
This also required adding a new hook to `ImageClient`, since there
wasn't a way of telling the ImageEditor that the full rect of the
image has changed (as when we rotate).
If we don't have enough layers to be able to scroll, the layers
are pushed to be at the top of the layer list. This doesn't make
much sense now that we are correctly drawing the layers in the
right order, so now we draw them justified towards the bottom.
Previously we were also clipping the bottom gadget slightly when
there were enough layers to scroll. Now, I'm adding some offset to
the total height to account for this and give equivalent spacing
from the top and bottom layers.
Previously the background layer was shown at the top, and layers
in front of it were shown below it. This was really unintuitive.
This patch fixes LayerListWidget to now properly differentiate
between the index of a gadget, and the index of a layer, since they
are essentially mirrored. I chose not to modify the order in which
layers are stored since back-to-front makes it really convenient
there.
This resets the DOM Inspector to a default state when re-opening it,
instead of it displaying the previous selection and properties, which
may be outdated. This is closer to how Chrome and Firefox behave.
Eventually, it probably makes sense to copy their behavior of selecting
the `<body>` element by default.
The direct-Document-access DOMTreeModel is no longer used, since the DOM
Inspector has to access the Document remotely over IPC. This commit
removes it, and renames DOMTreeJSONModel to take its place, since it no
longer has to differentiate itself from the non-JSON one.
In case that didn't make sense:
- Delete DOMTreeModel
- Rename DOMTreeJSONModel -> DOMTreeModel
Also simplify the logic by removing `Tab::view_dom_tree()`, and making
the Tab keep a pointer to the InspectorWidget instead of its Window,
since that's more often what we want to access.
We use TextEditor::on_modified_change() to update the modified window
flag, which it also works on file saves, so we don't have to unset
it there anymore!
It isn't really what the FIXME note asked about -- GUI::TextDocument
only sends us notifications about the changes, but overall I don't
think it's that bad, given that the whole window update logic is now
in one function. :^)
Previously it would only change the color of the ColorWidget itself,
but not make it the primary/secondary color. I think it feels nicer
this way, if I'm adding a color to the palette I likely want to use
it.
If you *really* need to only change the color of the palette, you
can just Ctrl+Middle click.
Previously, if you wanted to use a custom color, the only way to
do so was to first Ctrl+click on one of the pallette colors, which
would just change that palette item. Then, you would need to
manually click on that color.
Now, you can just click on the preview of the primary/secondary
color to open up the picker and only temporarily use the new color
without affecting the palette at all.
Only one place used this argument and it was to hold on to a strong ref
for the object. Since we already do that now, there's no need to keep
this argument around since this can be easily captured.
This commit contains no changes.
Without this, any resize of the GLContextWidget might leave the label
somewhere it shouldn't be. Toggling fullscreen is a single example of
that behavior.
The breadcrumbbar in here serves exactly the same purpose as the one in
File Manager. Given that, I believe it's worth to keep these two
visually consistent.
Removed the old custom checkbox selection code in the Visualization
menu and replaced them with GUI::ActionGroup with set_exclusive
enabled instead :^)
This way we can feed it the values if we wanted to change an existing
Guide and handle the default as before.
That we have to pass a String here is a bit ugly.
The height of the bottom color container was cut off at the bottom.
This adjusts the heights and also the primary/secondary color
widget so that it's in line.
Add a new Color category to the Filter menu. Add the Grayscale
filter under Filter->Color to turn the selected layer to grey colors.
Created GrayscaleFilter.h. Modify Filter.h to allow filters
without parameters.
The prior commits add the `DrawMode` enum to keep track of where
the shape is being drawn from. With this addition, the prior `Mode`
enum name is confusing, so this commit renames it to `FillMode` to
be more explicit :^)
Essentially the same logic as the prior commit, but now for the
`RectangleTool` class. Pressing `alt` lets you draw the rectangle
with the starting position as the center.
Like other common image editing applications, now if you press
`alt` while drawing an ellipse, it uses the starting position as
the center of the ellipse as opposed to one of the corners of the
bounding rect.
The EllipseTool class now keeps track of a `DrawMode`, which is
either `DrawMode::FromCorner` (default), or `DrawMode::FromCenter`
(the option added by this commit).
The `draw_using()` function was modified to now take in the start
and end positions and construct the `ellipse_intersecting_rect`
itself, since we need to construct it differently based on the
drawing mode.
This change removes the manually created model class
in order to use a generic GUI::ItemListModel.
Besides from code reusability, it also makes the list
searchable as you type.
This is the first step in transitioning Piano to a full LibDSP backend.
For now, the delay effect is replaced with a (mostly identical)
implementation in LibDSP.
The new ProcessorParameterSlider attaches to a LibDSP::Processor's
range parameter (LibDSP::ProcessorRangeParameter) and changes it
automatically. It also has the ability to update an external GUI::Label.
This is used for the three delay parameters and it will become useful
for auto-generating UI for Processors.
As Piano will later move to the RollNote defintions of LibDSP, it's a
good idea to already insert velocity and pitch support, even though it's
currently not used.
The default action (shown in bold) indicates what would you get
by double-clicking on file. Since it's a default option, I think it
deserves to be on top (together with alternative launch options). :^)
Also they're not task actions like "Extract .zip here" or "Add to
bookmarks".
No previous model index will be invalidated afterwards, so avoid
invalidating them.
Also fixes an issue where committing to an edit with the inline cell
editor makes the focused cell switch to A0.
Fixes#9677.
Previously, if you used one of the keyboard shortcuts to select a
different tool, it didn't change the cursor to the corresponding
one till you clicked somewhere / did something else to trigger an
update. This was pretty jarring since there's no indication as to
whether the tool change was successful or not.
This patch just calls `set_override_cursor()` when a valid active
tool is set to immediately update it.
In general, I think `opt == x` looks much nicer than
`opt.has_value() && opt.value() == x`, so I'm updating
the remaining few instances I could find with some regex
magic in my search.
1) The Sound Player visualizer couldn't deal with small sample buffers,
which occur on low sample rates. Now, it simply doesn't update its
buffer, meaning the display is broken on low sample rates. I'm not too
familiar with the visualizer to figure out a proper fix for now, but
this mitigates the issue (and "normal" sample rates still work).
2) Piano wouldn't buffer enough samples for small sample rates, so the
sample count per buffer is now increased to 2^12, introducing minor
amounts of (acceptable) lag.
All audio applications (aplay, Piano, Sound Player) respect the ability
of the system to have theoretically any sample rate. Therefore, they
resample their own audio into the system sample rate.
LibAudio previously had its loaders resample their own audio, even
though they expose their sample rate. This is now changed. The loaders
output audio data in their file's sample rate, which the user has to
query and resample appropriately. Resampling code from Buffer, WavLoader
and FlacLoader is removed.
Note that these applications only check the sample rate at startup,
which is reasonable (the user has to restart applications when changing
the sample rate). Fully dynamic adaptation could both lead to errors and
will require another IPC interface. This seems to be enough for now.
Some tools (e.g. ZoomTool) doesn't need layer to work. This commit
makes mouse events fire even if there is no layer. This fixes
a bug that ZoomTool didn't work when there is no layers.
This commit adds a Tool::MouseEvent struct, which contains events that
may be needed by tools: layer-relative, image-relative and raw (editor-
relative) event.
The raw event is used by ZoomTool to properly pan the view. This fixes
a bug which caused image to snap out of sight.
Let DirectoryView manage these actions itself. This matches what we
already do for a bunch of other actions, and prepares for the next
patch which will add Config::Listener to the mix.
The `open()` function of DirectoryView should change the current working
directory, so that the "Go to Location" menu item can process relative
paths correctly. Update other functions in DirectoryView to use `open()`
when opening a directory.
Prior to this if you typed "1+2=" you would not get the answer, instead
you'd be left with "2" on the screen; Calculator wanted you to hit the
enter key to get the answer. Now you can either use the enter or the
equal key to finish the operation and get the answer.
The FileManager/Window/Maximized flag was incorrectly read from the
ConfigServer using read_i32 instead of the intended read_bool function
call.
It is now being read with the correct type :^)
Instead of building the web DOM by hand, we now load an empty document
into an OutOfProcessWebView, and then append things to it by sending
little snippets of JavaScript to the host process. :^)
The IRC Client application made some sense while our main communication
hub was an IRC channel. Now that we've moved on, IRC is just a random
protocol with no particular relevance to this project.
This also has the benefit of removing one major client of the single-
process Web::InProcessWebView class.
This opens the DOM Inspector window, with the target element already
selected. (If the window is already open, it just selects the element.)
Note that this only applies to single-process mode for now. In OOP mode,
the "inspect element" action is disabled.
Load the wallpaper in a background action instead of on the main thread.
This reduces the time to first paint, and makes the UI feel more
responsive when clicking on wallpaper thumbnails.
The behavior of the method is changed slightly to return true if it
succesfully "loads" the empty path. This makes the API a little more
consistent, where "true" means "I made changes" and "false" means "I did
not make changes". No call sites currently use the return value, so no
changes are needed to those.
This is primarily to be able to remove the GenericLexer include out of
Format.h as well. A subsequent commit will add AK::Result to
GenericLexer, which will cause naming conflicts with other structures
named Result. This can be avoided (for now) by preventing nearly every
file in the system from implicitly including GenericLexer.
Other changes in this commit are to add the GenericLexer include to
files where it is missing.
Since we operate in screen space where y points down we need to reverse
what is considered clock wise and what is considered counter clockwise.
The rasterizer always expects triangles with a consistent winding order
thus swap 2 vertices if necessary to reverse the winding before passing
the triangle on to the rasterization stage.
glTexCoord should behave like glColor. It only updates a gl context
variable that contains the current texture coordinates. The vertex is
only actually created once glVertex is called.
Put the "Open in terminal" action next to the other navigation actions.
And separate the "New File" and "New Directory" actions from the actions
that operate on existing items.
Combine the "PCI devices" and "Processors" tabs into a "Hardware" tab.
And then remove the "Interrupts" tab because the number of received
IRQ's per device is not really useful information to expose in this GUI.
If the user needs this, he can check lsirq.
This allows the address bar to "select all" when initially gaining focus
as Firefox and Chrome do. A future improvement on this would be for the
Widget class to mange and provide focus transition as part of the events
instead of the UrlBox class. Currently focus is updated before the event
is provided to the UrlBox class.
This allows for typing [8] instead of [8, 8, 8, 8] to specify the same
margin on all edges, for example. The constructors follow CSS' style of
specifying margins. The added constructors are:
- Margins(int all): Sets the same margin on all edges.
- Margins(int vertical, int horizontal): Sets the first argument to top
and bottom margins, and the second argument to left and right margins.
- Margins(int top, int vertical, int bottom): Sets the first argument to
the top margin, the second argument to the left and right margins,
and the third argument to the bottom margin.
Previously the argument order for Margins was (left, top, right,
bottom). To make it more familiar and closer to how CSS does it, the
argument order is now (top, right, bottom, left).
While typing, we get the results from each provider asynchronously.
Previously, we were updating the UI for each result size,
which was causing a lot of flickering.
This fix creates a small timer to bundle the results
and reduce the number of UI updates per input.
This adds on_tool_activation() to Tool which GuideTool can use
to show guides, if they're hidden, when it's activated. Also
show guides on mousedown since there's no use in drawing invisible
guides.
Tightening of the update rect when firing the marching ants timer
unfortunately meant that only finalized selections would be redrawn,
and any new selection drawn outside of the update rect would not
update.
In #9373, /usr/local/bin was added to the unveiled directories to make
symbolization work on ports. This directory only exists if at least one
port is installed, so unveil would fail with ENOENT if we had none.
Earlier, we were using 0 value for characters not found in "map".
We should return failure for invalid inputs.
So, I have changed the return type of function to Optional<size_t>.
Also changed caller to handle Optional return.
Fixed convert_from_string() function to return correct output.
The value of a number is equal to sum of each digit multiplied by it's
positional weight.
This adds support for the Tools in PixelPaint to use different cursors
within ImageEditor. For now most of them get the crosshair cursor since
it's the most fitting, but in the future we will want to add custom
cursors.
This tightens the update rects for EraseTool, BrushTool And the marching
ants update in Selection. Inflate Selection update rect by 10x10 to
avoid misalignment when zoomed out.
Previously using PenTool while zoomed in could cause rendering glitches
since the update rect was misaligned with the image, most likely because
of rounding errors.
Loosening the rect with 1 pixel on either side takes care of this.
When exiting the terminal settings window, the opacity, bell and
maximum history size will be saved to the application config file.
Because the color scheme is neither configurable nor
will it be loaded on startup, it will not get saved for now.
Previously in Browser, when we navigate back from a page that has an
icon to a page that does not have an icon, the icon does not update and
the old icon is displayed because FrameLoader does not set the default
favicon when the favicon cannot be loaded. This patch ensures that
Browser receives a new icon bitmap every time a load takes place.
This patch adds the logic for the GuideTool. Pulling in from outside the
image creates a new Guide, moving a Guide outside of the image deletes
it and a Guide can be deleteted via the context menu.
A Guide is considered clicked when the cursor is less than 20 pixels
away from the line.
Previously changing tools while simultaneously using a widget like a
slider would result in a event_dispatch() failure.
Instead use a StackWidget to set the active widget.
Most of the models were just calling did_update anyway, which is
pointless since it can be unified to the base Model class. Instead, code
calling update() will now call invalidate(), which functions identically
and is more obvious in what it does.
Additionally, a default implementation is provided, which removes the
need to add empty implementations of update() for each model subclass.
Co-Authored-By: Ali Mohammad Pur <ali.mpfard@gmail.com>
This adds a tooltip to all the slider properties showing their
current value. Previously there was no indication of what
value they had. Also rename the SprayTool property 'thickness' to
'size' like BrushTool calls it.
Calculator now uses the KeypadValue class instead of double in
its internal calculations. By not constantly converting to
double back-and-forth, we do not use precision simply by, for
example, negating a number. This fixes#7484.
This commit adds a basic KeypadValue class which abstracts away
Keypad's internal representation in a slightly simpler format.
This will allow arithmetic operations in the Calculator to not
lose any precision. In cases where losing precision is necessary,
an explicit conversion operator to double is provided, as well as
an explicit constructor from double.
Add a column named 'Link status' to the Network tab in SystemMonitor
showing the speed and duplex if the link is up.
Add the link speed behind the existing text in the applet or show
'down' if the link is down.
Since this was missing, ProcessStateModel never received
model_did_update, and it was possible for the ProcessModel index to go
stale and show another process.
Fixes#9129.
The action never worked properly here. It used the selection
from the directory view, instead of the tree view.
Furthermore, the tree view isn't even editable.
Just making tree view editable wouldn't fix it -- it'd probably
need something like creating an on_stop_editing() function
in the AbstractView to change the path after the rename.
For now, I'll remove the action from the menu as a "temporary fix".
MailSettings: Add a GML file for Mail settings
MailSettings: Add an AF desktop file for Mail Settings
MailSettings: Unveil /res in mail settings, fix GML
MailSettings: Mail settings texteditor->textbox
MailSettings: Update mail username to correct category in settings
Modified Mail settings GML to properly represent ports >100
MailSettings: Update/fix mail settings GML
MailSettings: Adjust GML, add icons for mail settings
MailSettings: Change Okay button to OK
MailSettings: Change mail setting reset button to revert
MailSettings: Fix incorrect variable names in mail settings
MailSettings: Add newlines af EOF of all mail setting files
MailSettings: Mail settings linting issues fixed
MailSettings: Increase size of icon features
Code cleaning/styling changes as per gunnarbeutner review
Made settings descriptions more friendly per sin-ack review
MailSettings: Fixes as per PR comments
MailSettings: Fix checkbox weirdness
MailSettings: Adjust width of checkbox
MailSettings: Remove unneccessary update() call
MailSettings: Replace port SpinBox with ComboBox
MailSettings: Add colons to labels, remove port 110 option
MailSettings: Remove custom model, use ItemListModel
MailSettings: Change relative icon paths to absolute ones
We can use kill(pid,0) to check for kill permissions instead of relying
on file path access. Using 0 as signal does error checking but does not
send a signal.
This prevents GUI::TextBox and the `Paste & Go` action in the browser
from trying to paste a bitmap. Also, the paste action is enabled
and disabled on clipboard change to reflect if the clipboard data
can be pasted.
The original work was done in #2752
(deceb91c48 to be precise),
but unfortunately 2c772d1848 replaced
on_selection with on_selection_change, which caused the function
to never be executed, as it was reassigned a few lines below.
For example, the servers I tested this on sent "Subject" which matched
what I was checking for. However, some servers can send "SUBJECT" which
didn't match and would cause an assertion failure.
This utilises LibIMAP and LibWeb to provide an e-mail client.
The only way currently to connect to a server and login is with a
config file. This config file should be stored in ~/.config/Mail.ini
Here is an example config file:
```
[Connection]
Server=email.example.com
Port=993
TLS=true
[User]
Username=test@example.com
Password=Example!1
```
Since this is stored in plaintext and uses a less secure login method,
I'd recommend not using this on your main accounts :^)
This has been tested on Gmail and Outlook. For Gmail, you either have
to generate an app password if you have 2FA enabled, or enable access
from less secure apps in your account settings.
I found myself accidentally opening two assistants at once with the
Window+Space shortcut. Since only one assistant window is usable at the
same time, I made assistant only spawn 1 instance at most.