Jump to content

GSoC/2018/StatusReports/MichaelZhou: Difference between revisions

From KDE Community Wiki
Simeir (talk | contribs)
No edit summary
Simeir (talk | contribs)
No edit summary
 
(11 intermediate revisions by the same user not shown)
Line 1: Line 1:


== A New Palette Docker for Krita ==
== A New Palette Docker for Krita ==
Line 6: Line 7:


Task: https://phabricator.kde.org/T8646
Task: https://phabricator.kde.org/T8646
Code reviews:
  https://phabricator.kde.org/D14815
  https://phabricator.kde.org/D13750
  https://phabricator.kde.org/D13208


The proposal is on the task page.
The proposal is on the task page.


== Brief Introduction ==
== Brief Introduction ==


The new palette docker is designed and written to improve artists' experience of color management when using Krita.
The new palette docker is designed and written to improve artists' experience of color management when using Krita.


The original palette docker enable users to create new palettes that are shared with all works and maintain those palettes as a list of colors, though they are shown as matrices of colors.
The original palette docker enables users to create new palettes that are shared with all works and to maintain those palettes as a list of colors, though they are shown as matrices of colors.


Compared to the original palette docker, the new one is better mainly in these 3 ways:
Compared to the original palette docker, the new one is better mainly in these 3 ways:
# The colors are now not only shown, but also actually managed in matrices. Users can move them around freely in those matrices. They can leave empty slots or let the colors from some pattern if they want.
# The colors are now not only shown, but also actually managed in matrices. Users can move them around freely in those matrices. They can leave empty slots or let the colors from some pattern if they want.
# The palettes are associated with the `.kra` painting documents. Artists can create temporary palettes for a single file but don't need to worry about polluting the environment when editing other paintings. If they want to reuse palettes, they can also set the palettes to be 'global'.
# The palettes are associated with the '.kra' painting documents. Artists can create temporary palettes for a single file but don't need to worry about polluting the environment when editing other paintings. If they want to reuse palettes, they can also set the palettes to be 'global'.
# The docker now comes with a more intuitive GUI. Artists can now better edit the palettes and easily export and import them.
# The docker now comes with a more intuitive GUI. Artists can now better edit the palettes and easily export and import them.
== Done and To Do ==
All the features that are in the proposal are done. This involves the palette docker itself, the base classes in the underlying libraries relating to it, and other classes using these base classes. There are probably still some bugs, so I will need to work on locating and solving them.
While working on the palette docker, I got some new ideas, and also found some problems in the code base that I want to solve. Those include:
# Making it possible to select multiple swatches in the palette so that they can be drag/dropped or removed.
# Making it possible to drag the group names rows in the palette docker to reorder them.
# Use a list view (instead of a combo box) to show the groups in the dialog used to edit them, and making it easier to rename, delete and reorder groups. It should be like the layers docker.
# Use 'KisDlgInternalColorSelector' to replace 'KoColorSetWidget'. This way, the dependency that holds palette classes in kritawidgets will be resolved and it can be moved up into kritaui, and have some better tools to use.
# Improve 'KisDlgInternalColorSelector', making the triangular selector more smooth and the spin boxes show color values normally.


== Merged and not Merged ==
== Merged and not Merged ==


In the early phase of GSoC, I noticed that some base classes of the palettes can be reused in other places. Therefore, I did some refactoring to reuse them. The code reviews are here:
In the early phase of GSoC, I noticed that some base classes of the palettes can be reused in other places. Therefore, I did some refactoring to reuse them. The code reviews are here:
  https://phabricator.kde.org/D13750
 
  https://phabricator.kde.org/D13208
https://phabricator.kde.org/D13750
 
https://phabricator.kde.org/D13208
 
These 2 code reviews got merged, however, most of my work are in this code review, not yet merged.
These 2 code reviews got merged, however, most of my work are in this code review, not yet merged.
https://phabricator.kde.org/D14815
 
That is because merging parts of the change will break some functions. This project involves several widgets that cooperate with each other. If only some of the widgets got merged, master will have widgets that done work with each other well. Therefore, we decided to merge after everything is done.
https://phabricator.kde.org/D14815
 
That is because merging parts of the change will break some functions. This project involves several widgets that cooperate with each other. If only some of the widgets got merged, master will have widgets that don't work with each other well. Therefore, we decided to merge after everything is done.


== Details of usage ==
== Details of usage ==
Line 34: Line 55:
Each palette have the following attributes:
Each palette have the following attributes:


Column number  
{| class="wikitable"
  Number of columns.
|-
Name
! Attribute
  Name of the palette.
! Meaning
Filename
|-
  Path to where the palette is stored. For non-global palettes it is just a file name.  
! Column number  
Is global
| Number of columns.
  A palette is global if it isn't stored inside a `.kra` file, and can be accessed by all documents.
|-
Is read only
! Name
  Whether a palette is read only. Palettes that ship with Krita are usually read only.
| Name of the palette
|-
! Filename
| Path to where the palette is stored. For non-global palettes it is just a file name.  
|-
! Is global
| A palette is global if it isn't stored inside a '.kra' file, and can be accessed by all documents.
|-
! Is read only  
| Whether a palette is read only. Palettes that ship with Krita are usually read only.
|}


Also, each palette can have more than one groups. Each group has the same column number as the palette itself, and they each have a column number.
 
Also, each palette can have more than one groups. Each group has the same column number as the palette itself, and they each have a row number.


Every palette always has a main group that has no name. This group cannot be renamed or removed. One can set the row number of it to 0, though.
Every palette always has a main group that has no name. This group cannot be renamed or removed. One can set the row number of it to 0, though.


By clicking the `Edit this palette` button on the palette docker, one can open a dialog. In the dialog, one can set the attributes of the palette and the groups
[[File:PaletteDockerAndList.jpg]]


Each swatch in the palette docker also have more attributes than position and color. They each can have a name and string id. I actually don't know what the id is for... By double clicking a swatch, a dialog will pop up and let users edit it. One can also call the dialog by clicking the `modify this spot` button on the docker.
By clicking the 'Edit this palette' button on the palette docker, one can open a dialog. In the dialog, one can set the attributes of the palette and the groups.
 
[[File:PaletteEditorDialog.png]]
 
Each swatch in the palette docker also have more attributes than position and color. They each can have a name and string id. I actually don't know what the id is for... By double clicking a swatch, a dialog will pop up and let users edit it. One can also call the dialog by clicking the 'modify this spot' button on the docker.


The docker also supports drag and drop. By dragging and dropping one can move a swatch to a new position or switch it with another swatch.
The docker also supports drag and drop. By dragging and dropping one can move a swatch to a new position or switch it with another swatch.
Line 57: Line 93:
On the bottom left corner of the docker, there is a pop up button. After clicking it, the palette list widget will pop up.
On the bottom left corner of the docker, there is a pop up button. After clicking it, the palette list widget will pop up.


At the bottom of the palette list widget, there are 4 buttons. From left to right, they are respectively `Add a new palette`, `Export current palette to file`, `Import a new palette from file`, and `Remove current palette`. By default, `Add` and `Import` create non-global palettes. `Remove` can remove all palettes, global or non-global, except for those read only ones.
At the bottom of the palette list widget, there are 4 buttons. From left to right, they are respectively 'Add a new palette', 'Export current palette to file', 'Import a new palette from file', and 'Remove current palette'. By default, 'Add' and 'Import' create non-global palettes. 'Remove' can remove all palettes, global or non-global, except for those read only ones.
 
== Details of what has been done ==
 
'KoColorSet' and 'KisPaletteModel' have been heavily modified. Along with the new classes 'KisSwatch' and 'KisSwatchGroup', they form the underlying data structure of palettes, which are grouped color matrices.


== Done and To Do ==
The API of 'KoColorSet' and 'KisPaletteModel' have been modified. What I want is to let all the data handling be done in 'KisPaletteModel'. This is not done yet.
 
Surely, 'KisPaletteView' and 'KisPaletteDelegate' are modified to show the new matrices of colors.
 
The above group form the MVC system of palettes.


All the features that are in the proposal are done. This involves the palette docker itself, the base classes in the underlying libraries relating to it, and other classes using these base classes. There are probably still some bugs, so I will need to work on locating and solving them.
For making the modification of the palette tell krita that the document has changed, 'KisChangePaletteCommand' inheriting from KUndo2Command is created.


While working on the palette docker, I got some new ideas, and also found some problems in the code base that I want to solve. Those include:
For managing the list of palettes, 'KisPaletteListWidget' is created to replace 'KisColorsetChooser'.
# Making it possible to select multiple swatches in the palette so that they can be drag/dropped or removed.
# Making it possible to drag the group names rows in the palette docker to reorder them.
# Use a list view (instead of a combo box) to show the groups in the dialog used to edit them, and making it easier to rename, delete and reorder groups. It should be like the layers docker.
# Use KisDlgInternalColorSelector to replace KoColorSetWidget. This way, the dependency that holds palette classes in kritawidgets will be resolved and it can be moved up into kritaui, and have some better tools to use.
# Improve KisDlgInternalColorSelector, making the triangular selector more smooth and the spin boxes show color values normally.


== Details of what has been done ==
For the search box in the palette docker and the internal color selector, 'KisPaletteComboBox' is created. It syncs with a 'KisPaletteView' assigned to it.


KoColorSet and KisPaletteModel have been heavily modified. Along with the new classes KisSwatch and KisSwatchGroup, they form the underlying data structure of palettes, which are grouped color matrices.
Due the change in API and usage of classes, other classes that use the palettes are also affected. Those classes include 'KoColorSetWidget', 'KisDlgInternalColorSelector', 'KoEditColorSetDialog', 'KisToolLazyBrushOptionsWidget', and 'LayerSplit'.


The API of KoColorSet and KisPaletteModel have been modified. What I want is to let all the data handling be done in KisPaletteModel. This is not done yet.
'KoEditColorSetDialog' is removed because its functions can totally be replaced by the palette docker. 'KoColorSetWidget' is planned to be replaced by 'KisDlgInternalColorSelector'. 'LayerSplit' and 'KisToolLazyBrushOptionsWidget' are modified to adapt to the new API and tools.


Surely, KisPaletteView and KisPaletteDelegate are modified to show the new matrices of colors.
In order to make it possible to store palettes in '.kra', 'KisDocument' is modified. It have a new member called paletteList, a list of pointers to palettes that belong to it. In 'KoColorSet', toByteArray and fromByteArray are implemented so that it can save itself into a buffer and then be transferred and stored into '.kra'.


The above group form the MVC system of palettes.
Inside the docker, the setCanvas and unsetCanvas callbacks manipulates the resources server following the paletteList of the document being opened and closed.


For making the modification of the palette tell krita that the document has changed, KisChangePaletteCommand inheriting from KUndo2Command is created.
== '.kpl' ==


For managing the list of palettes, KisPaletteListWidget is created to replace KisColorsetChooser.
Original .kpl: https://phabricator.kde.org/T4121


For the search box in the palette docker and the internal color selector, KisPaletteComboBox is created. It syncs with a KisPaletteView assigned to it.
An example for the new 'colorset.xml' in the '.kpl:'
{{Input|<syntaxhighlight lang="xml" line>
<ColorSet columns="16" comment="" readonly="false" rows="3" version="1.0" name="PALETTE">
<ColorSetEntry bitdepth="U8" id="" spot="false" name="hair bright light">
  <RGB g="0.666666686534882" space="sRGB-elle-V2-srgbtrc.icc" r="0.898039221763611" b="0.549019634723663"/>
  <Position column="0" row="0"/>
</ColorSetEntry>
<ColorSetEntry bitdepth="U8" id="" spot="false" name="hair 1">
  <RGB g="0.313725501298904" space="sRGB-elle-V2-srgbtrc.icc" r="0.501960813999176" b="0.239215686917305"/>
  <Position column="1" row="0"/>
</ColorSetEntry>
<ColorSetEntry bitdepth="U8" id="" spot="false" name="hair mid">
  <RGB g="0.321568638086319" space="sRGB-elle-V2-srgbtrc.icc" r="0.533333361148834" b="0.250980406999588"/>
  <Position column="2" row="0"/>
</ColorSetEntry>
<ColorSetEntry bitdepth="U8" id="" spot="false" name="hair dark">
  <RGB g="0.129411771893501" space="sRGB-elle-V2-srgbtrc.icc" r="0.30588236451149" b="0.109803922474384"/>
  <Position column="3" row="0"/>
</ColorSetEntry>
<ColorSetEntry bitdepth="U8" id="" spot="false" name="hair 3">
  <RGB g="0.211764708161354" space="sRGB-elle-V2-srgbtrc.icc" r="0.380392163991928" b="0.18823529779911"/>
  <Position column="4" row="0"/>
</ColorSetEntry>
<Group rows="3" name="skin">
  <ColorSetEntry bitdepth="U8" id="" spot="false" name="skin 0">
  <RGB g="0.992156863212585" space="sRGB-elle-V2-srgbtrc.icc" r="1" b="0.925490200519562"/>
  <Position column="0" row="0"/>
  </ColorSetEntry>
  <ColorSetEntry bitdepth="U8" id="" spot="false" name="skin 1">
  <RGB g="0.949019610881805" space="sRGB-elle-V2-srgbtrc.icc" r="1" b="0.874509811401367"/>
  <Position column="1" row="0"/>
  </ColorSetEntry>
  <ColorSetEntry bitdepth="U8" id="" spot="false" name="skin 2">
  <RGB g="0.82745099067688" space="sRGB-elle-V2-srgbtrc.icc" r="0.941176474094391" b="0.796078443527222"/>
  <Position column="2" row="0"/>
  </ColorSetEntry>
  <ColorSetEntry bitdepth="U8" id="" spot="false" name="skin 4">
  <RGB g="0.65490198135376" space="sRGB-elle-V2-srgbtrc.icc" r="0.819607853889465" b="0.619607865810394"/>
  <Position column="3" row="0"/>
  </ColorSetEntry>
</Group>
</ColorSet>
</syntaxhighlight>}}


Due the change in API and usage of classes, other classes that use the palettes are also affected. Those classes include KoColorSetWidget, KisDlgInternalColorSelector, KoEditColorSetDialog, KisToolLazyBrushOptionsWidget, and LayerSplit.
Following are the differences from the original '.kpl':


KoEditColorSetDialog is removed because its functions can totally be replaced by the palette docker. KoColorSetWidget is planned to be replaced by KisDlgInternalColorSelector. LayerSplit and KisToolLazyBrushOptionsWidget are modified to adapt to the new API and tools.
The new rows and readonly attribute in the 'ColorSet' tag. rows here means the row number of the main group. This attribute also exists and have the same meaning in the 'Group' tags.


In order to make it possible to store palettes in `.kra`, KisDocument is modified. It have a new member called paletteList, a list of pointers to palettes that belong to it. In KoColorSet, toByteArray and fromByteArray are implemented so that it can save itself into a buffer and then be transferred and stored into `.kra`.
A Position tag now exists for each 'ColorSetEntry'. It decides the position of the swatch defined by the 'ColorSetEntry' tag.


Inside the docker, the setCanvas and unsetCanvas callbacks manipulates the resources server following the paletteList of the document being opened and closed.
== Other Related links ==
Blog posts:
  https://simeir.github.io/kde/2018/05/13/First-Post.html
  https://simeir.github.io/kde/2018/06/22/Second-Post.html
  https://simeir.github.io/kde/2018/06/29/Third-Post.html
  https://simeir.github.io/kde/2018/07/13/Fifth-Post.html

Latest revision as of 08:45, 14 August 2018


A New Palette Docker for Krita

Status report for a Google Summer of Code project.

Task: https://phabricator.kde.org/T8646

Code reviews:

 https://phabricator.kde.org/D14815
 https://phabricator.kde.org/D13750
 https://phabricator.kde.org/D13208

The proposal is on the task page.

Brief Introduction

The new palette docker is designed and written to improve artists' experience of color management when using Krita.

The original palette docker enables users to create new palettes that are shared with all works and to maintain those palettes as a list of colors, though they are shown as matrices of colors.

Compared to the original palette docker, the new one is better mainly in these 3 ways:

  1. The colors are now not only shown, but also actually managed in matrices. Users can move them around freely in those matrices. They can leave empty slots or let the colors from some pattern if they want.
  2. The palettes are associated with the '.kra' painting documents. Artists can create temporary palettes for a single file but don't need to worry about polluting the environment when editing other paintings. If they want to reuse palettes, they can also set the palettes to be 'global'.
  3. The docker now comes with a more intuitive GUI. Artists can now better edit the palettes and easily export and import them.

Done and To Do

All the features that are in the proposal are done. This involves the palette docker itself, the base classes in the underlying libraries relating to it, and other classes using these base classes. There are probably still some bugs, so I will need to work on locating and solving them.

While working on the palette docker, I got some new ideas, and also found some problems in the code base that I want to solve. Those include:

  1. Making it possible to select multiple swatches in the palette so that they can be drag/dropped or removed.
  2. Making it possible to drag the group names rows in the palette docker to reorder them.
  3. Use a list view (instead of a combo box) to show the groups in the dialog used to edit them, and making it easier to rename, delete and reorder groups. It should be like the layers docker.
  4. Use 'KisDlgInternalColorSelector' to replace 'KoColorSetWidget'. This way, the dependency that holds palette classes in kritawidgets will be resolved and it can be moved up into kritaui, and have some better tools to use.
  5. Improve 'KisDlgInternalColorSelector', making the triangular selector more smooth and the spin boxes show color values normally.

Merged and not Merged

In the early phase of GSoC, I noticed that some base classes of the palettes can be reused in other places. Therefore, I did some refactoring to reuse them. The code reviews are here:

https://phabricator.kde.org/D13750

https://phabricator.kde.org/D13208

These 2 code reviews got merged, however, most of my work are in this code review, not yet merged.

https://phabricator.kde.org/D14815

That is because merging parts of the change will break some functions. This project involves several widgets that cooperate with each other. If only some of the widgets got merged, master will have widgets that don't work with each other well. Therefore, we decided to merge after everything is done.

Details of usage

Each palette have the following attributes:

Attribute Meaning
Column number Number of columns.
Name Name of the palette
Filename Path to where the palette is stored. For non-global palettes it is just a file name.
Is global A palette is global if it isn't stored inside a '.kra' file, and can be accessed by all documents.
Is read only Whether a palette is read only. Palettes that ship with Krita are usually read only.


Also, each palette can have more than one groups. Each group has the same column number as the palette itself, and they each have a row number.

Every palette always has a main group that has no name. This group cannot be renamed or removed. One can set the row number of it to 0, though.

By clicking the 'Edit this palette' button on the palette docker, one can open a dialog. In the dialog, one can set the attributes of the palette and the groups.

Each swatch in the palette docker also have more attributes than position and color. They each can have a name and string id. I actually don't know what the id is for... By double clicking a swatch, a dialog will pop up and let users edit it. One can also call the dialog by clicking the 'modify this spot' button on the docker.

The docker also supports drag and drop. By dragging and dropping one can move a swatch to a new position or switch it with another swatch.

On the bottom left corner of the docker, there is a pop up button. After clicking it, the palette list widget will pop up.

At the bottom of the palette list widget, there are 4 buttons. From left to right, they are respectively 'Add a new palette', 'Export current palette to file', 'Import a new palette from file', and 'Remove current palette'. By default, 'Add' and 'Import' create non-global palettes. 'Remove' can remove all palettes, global or non-global, except for those read only ones.

Details of what has been done

'KoColorSet' and 'KisPaletteModel' have been heavily modified. Along with the new classes 'KisSwatch' and 'KisSwatchGroup', they form the underlying data structure of palettes, which are grouped color matrices.

The API of 'KoColorSet' and 'KisPaletteModel' have been modified. What I want is to let all the data handling be done in 'KisPaletteModel'. This is not done yet.

Surely, 'KisPaletteView' and 'KisPaletteDelegate' are modified to show the new matrices of colors.

The above group form the MVC system of palettes.

For making the modification of the palette tell krita that the document has changed, 'KisChangePaletteCommand' inheriting from KUndo2Command is created.

For managing the list of palettes, 'KisPaletteListWidget' is created to replace 'KisColorsetChooser'.

For the search box in the palette docker and the internal color selector, 'KisPaletteComboBox' is created. It syncs with a 'KisPaletteView' assigned to it.

Due the change in API and usage of classes, other classes that use the palettes are also affected. Those classes include 'KoColorSetWidget', 'KisDlgInternalColorSelector', 'KoEditColorSetDialog', 'KisToolLazyBrushOptionsWidget', and 'LayerSplit'.

'KoEditColorSetDialog' is removed because its functions can totally be replaced by the palette docker. 'KoColorSetWidget' is planned to be replaced by 'KisDlgInternalColorSelector'. 'LayerSplit' and 'KisToolLazyBrushOptionsWidget' are modified to adapt to the new API and tools.

In order to make it possible to store palettes in '.kra', 'KisDocument' is modified. It have a new member called paletteList, a list of pointers to palettes that belong to it. In 'KoColorSet', toByteArray and fromByteArray are implemented so that it can save itself into a buffer and then be transferred and stored into '.kra'.

Inside the docker, the setCanvas and unsetCanvas callbacks manipulates the resources server following the paletteList of the document being opened and closed.

'.kpl'

Original .kpl: https://phabricator.kde.org/T4121

An example for the new 'colorset.xml' in the '.kpl:'

<ColorSet columns="16" comment="" readonly="false" rows="3" version="1.0" name="PALETTE">
 <ColorSetEntry bitdepth="U8" id="" spot="false" name="hair bright light">
  <RGB g="0.666666686534882" space="sRGB-elle-V2-srgbtrc.icc" r="0.898039221763611" b="0.549019634723663"/>
  <Position column="0" row="0"/>
 </ColorSetEntry>
 <ColorSetEntry bitdepth="U8" id="" spot="false" name="hair 1">
  <RGB g="0.313725501298904" space="sRGB-elle-V2-srgbtrc.icc" r="0.501960813999176" b="0.239215686917305"/>
  <Position column="1" row="0"/>
 </ColorSetEntry>
 <ColorSetEntry bitdepth="U8" id="" spot="false" name="hair mid">
  <RGB g="0.321568638086319" space="sRGB-elle-V2-srgbtrc.icc" r="0.533333361148834" b="0.250980406999588"/>
  <Position column="2" row="0"/>
 </ColorSetEntry>
 <ColorSetEntry bitdepth="U8" id="" spot="false" name="hair dark">
  <RGB g="0.129411771893501" space="sRGB-elle-V2-srgbtrc.icc" r="0.30588236451149" b="0.109803922474384"/>
  <Position column="3" row="0"/>
 </ColorSetEntry>
 <ColorSetEntry bitdepth="U8" id="" spot="false" name="hair 3">
  <RGB g="0.211764708161354" space="sRGB-elle-V2-srgbtrc.icc" r="0.380392163991928" b="0.18823529779911"/>
  <Position column="4" row="0"/>
 </ColorSetEntry>
 <Group rows="3" name="skin">
  <ColorSetEntry bitdepth="U8" id="" spot="false" name="skin 0">
   <RGB g="0.992156863212585" space="sRGB-elle-V2-srgbtrc.icc" r="1" b="0.925490200519562"/>
   <Position column="0" row="0"/>
  </ColorSetEntry>
  <ColorSetEntry bitdepth="U8" id="" spot="false" name="skin 1">
   <RGB g="0.949019610881805" space="sRGB-elle-V2-srgbtrc.icc" r="1" b="0.874509811401367"/>
   <Position column="1" row="0"/>
  </ColorSetEntry>
  <ColorSetEntry bitdepth="U8" id="" spot="false" name="skin 2">
   <RGB g="0.82745099067688" space="sRGB-elle-V2-srgbtrc.icc" r="0.941176474094391" b="0.796078443527222"/>
   <Position column="2" row="0"/>
  </ColorSetEntry>
  <ColorSetEntry bitdepth="U8" id="" spot="false" name="skin 4">
   <RGB g="0.65490198135376" space="sRGB-elle-V2-srgbtrc.icc" r="0.819607853889465" b="0.619607865810394"/>
   <Position column="3" row="0"/>
  </ColorSetEntry>
 </Group>
</ColorSet>

Following are the differences from the original '.kpl':

The new rows and readonly attribute in the 'ColorSet' tag. rows here means the row number of the main group. This attribute also exists and have the same meaning in the 'Group' tags.

A Position tag now exists for each 'ColorSetEntry'. It decides the position of the swatch defined by the 'ColorSetEntry' tag.

Other Related links

Blog posts:

 https://simeir.github.io/kde/2018/05/13/First-Post.html
 https://simeir.github.io/kde/2018/06/22/Second-Post.html
 https://simeir.github.io/kde/2018/06/29/Third-Post.html
 https://simeir.github.io/kde/2018/07/13/Fifth-Post.html