Commit c4b70a37 authored by Dmitry Kazakov's avatar Dmitry Kazakov

Merge remote-tracking branch 'origin/master' into krita-testing-kazakov

Conflicts:
	krita/plugins/extensions/dockers/advancedcolorselector/kis_color_selector_ring.h
	krita/ui/kis_popup_palette.cpp
	krita/ui/kis_view2.cpp
parents 22a5385f b9dc096c
......@@ -52,11 +52,13 @@ set(CALLIGRA_GIT_SHA1_STRING "")
include(GetGitRevisionDescription)
get_git_head_revision(GIT_REFSPEC GIT_SHA1)
get_git_branch(GIT_BRANCH)
if(GIT_SHA1)
if(GIT_SHA1 AND GIT_BRANCH)
string(SUBSTRING ${GIT_SHA1} 0 7 GIT_SHA1)
set(CALLIGRA_GIT_SHA1_STRING ${GIT_SHA1})
endif(GIT_SHA1)
set(CALLIGRA_GIT_BRANCH_STRING ${GIT_BRANCH})
endif()
########################
#########################
......@@ -175,7 +177,7 @@ calligra_define_product(EXTRA_PROPERTIES "Plugin for the KDE file properties dia
calligra_define_product(EXTRA_THUMBNAIL "Plugins for KDE filesystem thumbnailing" NEEDS CALLIGRA_LIBS)
calligra_define_product(EXTRA_QUICKPRINT "Plugin for the filemanager adding a \"Print\" action")
calligra_define_product(EXTRA_FILEMANAGER_TEMPLATES "File templates for filemanager")
calligra_define_product(OKULARODPGENERATOR "Plugin for Okular adding support for ODP and MS PPT/PPTX" NEEDS STAGE_PART)
calligra_define_product(OKULARODPGENERATOR "Plugin for Okular adding support for ODP" NEEDS STAGE_PART)
# more plugins
calligra_define_product(PLUGIN_COLORENGINES "Colorengine plugins" NEEDS CALLIGRA_LIBS)
calligra_define_product(PLUGIN_MUSICSHAPE "Music shape plugin" NEEDS CALLIGRA_LIBS)
......@@ -278,6 +280,9 @@ calligra_define_product(PLAN "Full Plan (for Desktop)" NEEDS PLAN_APP WANTS FI
calligra_define_product(BRAINDUMP "Full Braindump (for Desktop)" NEEDS BRAINDUMP_APP)
calligra_define_product(ACTIVE "Calligra Active" NEEDS SHEETS_PART STAGE_PART WORDS_PART)
calligra_define_product(CALLIGRA "General Calligra program starter" NEEDS CALLIGRA_LIBS)
# more extras
calligra_define_product(OKULARGENERATOR_PPT "Plugin for Okular extended with support for PPT" NEEDS OKULARODPGENERATOR FILTER_PPT_TO_ODP)
calligra_define_product(OKULARGENERATOR_PPTX "Plugin for Okular extended with support for PPTX" NEEDS OKULARODPGENERATOR FILTER_PPTX_TO_ODP)
# developer utils
calligra_define_product(DEVTOOLS "Tools for developers")
calligra_define_product(CSTESTER "cstester " NEEDS SHEETS_PART STAGE_PART WORDS_PART)
......
......@@ -124,6 +124,33 @@ function(git_describe _var)
set(${_var} "${out}" PARENT_SCOPE)
endfunction()
function(get_git_branch _var)
if(NOT GIT_FOUND)
find_package(Git QUIET)
endif()
if(NOT GIT_FOUND)
set(${_var} "GIT-NOTFOUND" PARENT_SCOPE)
return()
endif()
execute_process(COMMAND
"${GIT_EXECUTABLE}"
symbolic-ref --short HEAD
WORKING_DIRECTORY
"${CMAKE_SOURCE_DIR}"
RESULT_VARIABLE
res
OUTPUT_VARIABLE
out
ERROR_QUIET
OUTPUT_STRIP_TRAILING_WHITESPACE)
if(NOT res EQUAL 0)
set(out "${out}-${res}-NOTFOUND")
endif()
set(${_var} "${out}" PARENT_SCOPE)
endfunction()
function(git_get_exact_tag _var)
git_describe(out --exact-match ${ARGN})
set(${_var} "${out}" PARENT_SCOPE)
......
......@@ -48,6 +48,8 @@ set( CALLIGRA_SHOULD_BUILD_PRODUCTS
EXTRA_QUICKPRINT
EXTRA_FILEMANAGER_TEMPLATES
OKULARODPGENERATOR
OKULARGENERATOR_PPT
OKULARGENERATOR_PPTX
# developer utils
CSTESTER
DEVTOOLS
......
......@@ -46,4 +46,6 @@ set( CALLIGRA_SHOULD_BUILD_PRODUCTS
EXTRA_QUICKPRINT
EXTRA_FILEMANAGER_TEMPLATES
OKULARODPGENERATOR
OKULARGENERATOR_PPT
OKULARGENERATOR_PPTX
)
......@@ -196,6 +196,8 @@ QString platformToStringWin(QSysInfo::WinVersion version)
return "Windows 7";
case QSysInfo::WV_WINDOWS8:
return "Windows 8";
case QSysInfo::WV_WINDOWS8_1:
return "Windows 8.1";
default:
return "Unknown Windows version";
};
......
......@@ -419,7 +419,8 @@ void MainWindow::adjustZoomOnDocumentChangedAndStuff()
KisView2* view = qobject_cast<KisView2*>(d->desktopView->rootView());
// We have to set the focus on the view here, otherwise the toolmanager is unaware of which
// canvas should be handled.
d->desktopView->rootView()->setFocus();
view->canvasControllerWidget()->setFocus();
view->setFocus();
QPoint center = view->rect().center();
view->canvasControllerWidget()->zoomRelativeToPoint(center, 0.9);
qApp->processEvents();
......@@ -435,6 +436,10 @@ void MainWindow::adjustZoomOnDocumentChangedAndStuff()
qApp->processEvents();
d->toDesktop->setEnabled(true);
}
// Ensure that we do, in fact, have the brush tool selected on the currently active canvas
KoToolManager::instance()->switchToolRequested( "InteractionTool" );
qApp->processEvents();
KoToolManager::instance()->switchToolRequested( "KritaShape/KisToolBrush" );
}
void MainWindow::documentChanged()
......
......@@ -54,6 +54,11 @@ struct ViewModeSynchronisationObject {
QString activeToolId;
KoGridData* gridData;
// Mirror-axes
QPointF mirrorAxesCenter;
bool mirrorHorizontal;
bool mirrorVertical;
};
class ViewModeSwitchEvent : public QEvent
......
......@@ -85,8 +85,10 @@ DesktopViewProxy::DesktopViewProxy(MainWindow* mainWindow, KoMainWindow* parent)
reloadAction->disconnect(d->desktopView);
connect(reloadAction, SIGNAL(triggered(bool)), this, SLOT(reload()));
QAction* loadExistingAsNewAction = d->desktopView->actionCollection()->action("file_import_file");
loadExistingAsNewAction->disconnect(d->desktopView);
connect(loadExistingAsNewAction, SIGNAL(triggered(bool)), this, SLOT(loadExistingAsNew()));
//Hide the "Load existing as new" action. It serves little purpose and currently
//does the same as open. We cannot just remove it from the action collection though
//since that causes a crash in KoMainWindow.
loadExistingAsNewAction->setVisible(false);
// Recent files need a touch more work, as they aren't simply an action.
KRecentFilesAction* recent = qobject_cast<KRecentFilesAction*>(d->desktopView->actionCollection()->action("file_open_recent"));
......
......@@ -25,4 +25,9 @@ KritaSketchBase {
onWidthChanged: Constants.setGridWidth( width / Constants.GridColumns );
onHeightChanged: Constants.setGridHeight( height / Constants.GridRows );
window: mainWindow;
Component.onCompleted: {
Constants.setGridWidth( width / Constants.GridColumns );
Constants.setGridHeight( height / Constants.GridRows );
}
}
......@@ -61,11 +61,6 @@ QString KisPaintOpFactory::pixmap()
return "";
}
QString KisPaintOpFactory::categoryExperimental()
{
return i18nc("Category of brush engines", "Experimental");
}
QString KisPaintOpFactory::categoryStable()
{
return i18nc("Category of brush engines", "Stable");
......
......@@ -57,7 +57,6 @@ public:
virtual ~KisPaintOpFactory() {}
static QString categoryStable();
static QString categoryExperimental();
#ifdef HAVE_THREADED_TEXT_RENDERING_WORKAROUND
virtual void preinitializePaintOpIfNeeded(const KisPaintOpSettingsSP settings);
......
......@@ -125,7 +125,14 @@ bool KisPaintOpPreset::load()
QFile file(filename());
if (file.size() == 0) return false;
QImageReader reader(filename(), "PNG");
bool res = loadFromDevice(&file);
return true;
}
bool KisPaintOpPreset::loadFromDevice(QIODevice *dev)
{
QImageReader reader(dev, "PNG");
QString version = reader.text("version");
QString preset = reader.text("preset");
......@@ -137,8 +144,7 @@ bool KisPaintOpPreset::load()
}
QImage img;
if (!reader.read(&img))
{
if (!reader.read(&img)) {
dbgImage << "Fail to decode PNG";
return false;
}
......@@ -152,12 +158,16 @@ bool KisPaintOpPreset::load()
if (!doc.setContent(preset)) {
return false;
}
fromXML(doc.documentElement());
if (!m_d->settings) {
return false;
}
setValid(true);
setImage(img);
return true;
}
......@@ -175,7 +185,7 @@ bool KisPaintOpPreset::save()
QFile f(filename());
f.open(QFile::WriteOnly);
return save(&f);
return saveToDevice(&f);
}
void KisPaintOpPreset::toXML(QDomDocument& doc, QDomElement& elt) const
......@@ -193,15 +203,13 @@ void KisPaintOpPreset::fromXML(const QDomElement& presetElt)
setName(presetElt.attribute("name"));
QString paintopid = presetElt.attribute("paintopid");
if (paintopid.isEmpty())
{
if (paintopid.isEmpty()) {
dbgImage << "No paintopid attribute";
setValid(false);
return;
}
if (KisPaintOpRegistry::instance()->get(paintopid) == 0)
{
if (KisPaintOpRegistry::instance()->get(paintopid) == 0) {
dbgImage << "No paintop " << paintopid;
setValid(false);
return;
......@@ -210,8 +218,7 @@ void KisPaintOpPreset::fromXML(const QDomElement& presetElt)
KoID id(paintopid, "");
KisPaintOpSettingsSP settings = KisPaintOpRegistry::instance()->settings(id, 0);
if (!settings)
{
if (!settings) {
setValid(false);
qWarning() << "Could not load settings for preset" << paintopid;
return;
......@@ -225,7 +232,7 @@ QByteArray KisPaintOpPreset::generateMD5() const
QByteArray ba;
QBuffer buf(&ba);
buf.open(QBuffer::WriteOnly);
save(&buf);
saveToDevice(&buf);
buf.close();
if (!ba.isEmpty()) {
......@@ -237,9 +244,9 @@ QByteArray KisPaintOpPreset::generateMD5() const
return ba;
}
bool KisPaintOpPreset::save(QIODevice *io) const
bool KisPaintOpPreset::saveToDevice(QIODevice *dev) const
{
QImageWriter writer(io, "PNG");
QImageWriter writer(dev, "PNG");
QDomDocument doc;
QDomElement root = doc.createElement("Preset");
......
......@@ -57,9 +57,11 @@ public:
KisPaintOpSettingsSP settings() const;
bool load();
bool loadFromDevice(QIODevice *dev);
bool save();
bool saveToDevice(QIODevice* dev) const;
void toXML(QDomDocument& doc, QDomElement& elt) const;
void fromXML(const QDomElement& elt);
......@@ -78,8 +80,6 @@ protected:
private:
bool save(QIODevice *io) const;
struct Private;
Private * const m_d;
};
......
......@@ -59,7 +59,7 @@ public:
/**
* This function is called by a tool when the mouse is pressed. It's useful if
* the paintop needs mouse interaction for instance in the case of the duplicate op.
* the paintop needs mouse interaction for instance in the case of the clone op.
* If the tool is supposed to ignore the event, the paint op should return false
* and if the tool is supposed to use the event, return true.
*/
......@@ -107,7 +107,7 @@ public:
/**
* @return the composite op it to which the indirect painting device
* should be initialized to. This is used by duplicate op to reset
* should be initialized to. This is used by clone op to reset
* the composite op to COMPOSITE_COPY
*/
virtual QString indirectPaintingCompositeOp() const;
......@@ -132,13 +132,13 @@ public:
*/
enum OutlineMode {
CursorIsOutline = 1, ///< When this mode is set, an outline is painted around the cursor
CursorIsNotOutline = 2 ///< Currently, this mode means that there is no outline active. It used to mean using of QImage-based outlines (e.g. for duplicate tool) but it was not implemented.
CursorIsNotOutline = 2 ///< Currently, this mode means that there is no outline active. It used to mean using of QImage-based outlines (e.g. for clone tool) but it was not implemented.
};
/**
* Returns the brush outline in pixel coordinates. Tool is responsible for conversion into view coordinates.
* Outline mode has to be passed to the paintop which builds the outline as some paintops have to paint outline
* always like duplicate paintop indicating the duplicate position
* always like clone paintop indicating the duplicate position
*/
virtual QPainterPath brushOutline(const KisPaintInformation &info, OutlineMode mode) const;
......
......@@ -30,8 +30,8 @@ class QDomElement;
class QDomDocument;
const KoID DefaultId("default", ki18n("Default")); ///< generate Krita default mask generator
const KoID SoftId("soft", ki18n("Soft brush")); ///< generate brush mask from former softbrush paintop, where softness is based on curve
const KoID GaussId("gauss", ki18n("Gaussian brush")); ///< generate brush mask with a Gaussian-blurred edge
const KoID SoftId("soft", ki18n("Soft")); ///< generate brush mask from former softbrush paintop, where softness is based on curve
const KoID GaussId("gauss", ki18n("Gaussian")); ///< generate brush mask with a Gaussian-blurred edge
static const int OVERSAMPLING = 4;
......
......@@ -1668,5 +1668,11 @@ bool KisImage::wrapAroundModeActive() const
m_d->scheduler->wrapAroundModeSupported();
}
void KisImage::notifyNodeCollpasedChanged()
{
emit sigNodeCollapsedChanged();
}
#include "kis_image.moc"
......@@ -521,6 +521,11 @@ public:
*/
bool wrapAroundModeActive() const;
/**
* Notifies that the node collapsed state has changed
*/
void notifyNodeCollpasedChanged();
public:
void startIsolatedMode(KisNodeSP node);
void stopIsolatedMode();
......@@ -654,6 +659,12 @@ signals:
*/
void sigIsolatedModeChanged();
/**
* Emitted when one or more nodes changed the collapsed state
*
*/
void sigNodeCollapsedChanged();
public slots:
KisCompositeProgressProxy* compositeProgressProxy();
......
......@@ -62,6 +62,7 @@ public:
bool process(KisNode* node) {
if(m_mode == STORE) {
m_layerComposition->m_visibilityMap[node->uuid()] = node->visible();
m_layerComposition->m_collapsedMap[node->uuid()] = node->collapsed();
} else {
bool newState = false;
if(m_layerComposition->m_visibilityMap.contains(node->uuid())) {
......@@ -71,6 +72,9 @@ public:
node->setVisible(m_layerComposition->m_visibilityMap[node->uuid()]);
node->setDirty();
}
if(m_layerComposition->m_collapsedMap.contains(node->uuid())) {
node->setCollapsed(m_layerComposition->m_collapsedMap[node->uuid()]);
}
}
return true;
......@@ -80,7 +84,7 @@ private:
Mode m_mode;
};
KisLayerComposition::KisLayerComposition(KisImageWSP image, const QString& name): m_image(image), m_name(name)
KisLayerComposition::KisLayerComposition(KisImageWSP image, const QString& name): m_image(image), m_name(name), m_exportEnabled(true)
{
}
......@@ -90,6 +94,11 @@ KisLayerComposition::~KisLayerComposition()
}
void KisLayerComposition::setName(const QString& name)
{
m_name = name;
}
QString KisLayerComposition::name()
{
return m_name;
......@@ -111,6 +120,17 @@ void KisLayerComposition::apply()
}
KisCompositionVisitor visitor(this, KisCompositionVisitor::APPLY);
m_image->rootLayer()->accept(visitor);
m_image->notifyNodeCollpasedChanged();
}
void KisLayerComposition::setExportEnabled ( bool enabled )
{
m_exportEnabled = enabled;
}
bool KisLayerComposition::isExportEnabled()
{
return m_exportEnabled;
}
void KisLayerComposition::setVisible(QUuid id, bool visible)
......@@ -118,16 +138,27 @@ void KisLayerComposition::setVisible(QUuid id, bool visible)
m_visibilityMap[id] = visible;
}
void KisLayerComposition::setCollapsed ( QUuid id, bool collapsed )
{
m_collapsedMap[id] = collapsed;
}
void KisLayerComposition::save(QDomDocument& doc, QDomElement& element)
{
QDomElement compositionElement = doc.createElement("composition");
compositionElement.setAttribute("name", m_name);
compositionElement.setAttribute("exportEnabled", m_exportEnabled);
QMapIterator<QUuid, bool> iter(m_visibilityMap);
while (iter.hasNext()) {
iter.next();
QDomElement valueElement = doc.createElement("value");
valueElement.setAttribute("uuid", iter.key().toString());
valueElement.setAttribute("visible", iter.value());
kDebug() << "contains" << m_collapsedMap.contains(iter.key());
if (m_collapsedMap.contains(iter.key())) {
kDebug() << "colapsed :" << m_collapsedMap[iter.key()];
valueElement.setAttribute("collapsed", m_collapsedMap[iter.key()]);
}
compositionElement.appendChild(valueElement);
}
element.appendChild(compositionElement);
......
......@@ -38,6 +38,11 @@ public:
KisLayerComposition(KisImageWSP image, const QString& name);
~KisLayerComposition();
/**
* Sets name of the composition
*/
void setName(const QString& name);
/**
* Name of the composition as show in the docker
* \return name of the composition
......@@ -54,14 +59,29 @@ public:
*/
void apply();
/**
* Set the export enabled flag, if false the compositions will not be exported
*/
void setExportEnabled(bool enabled);
/**
* Export enabled flag, if false the compositions will not be exported
* \return name of the composition
*/
bool isExportEnabled();
void setVisible(QUuid id, bool visible);
void setCollapsed(QUuid id, bool collapsed);
void save(QDomDocument& doc, QDomElement& element);
private:
KisImageWSP m_image;
QString m_name;
QMap<QUuid, bool> m_visibilityMap;
QMap<QUuid, bool> m_collapsedMap;
bool m_exportEnabled;
friend class KisCompositionVisitor;
};
......
......@@ -582,7 +582,7 @@ public:
* Set the paintop preset to use. If @param image is given,
* the paintop will be created using this image as parameter.
* Some paintops really want to know about the image they work
* for, e.g. the duplicate paintop.
* for, e.g. the clone paintop.
*/
void setPaintOpPreset(KisPaintOpPresetSP preset, KisImageWSP image);
......
......@@ -73,8 +73,22 @@ void KisPropertiesConfiguration::fromXML(const QDomElement& e)
QDomElement e = n.toElement();
if (!e.isNull()) {
if (e.tagName() == "param") {
// XXX Convert the variant pro-actively to the right type?
d->properties[e.attribute("name")] = QVariant(e.text());
// If the file contains the new type parameter introduced in Krita act on it
// Else invoke old behaviour
if(e.attributes().contains("type"))
{
QString type = e.attribute("type");
QString name = e.attribute("name");
QString value = e.text();
if(type == "bytearray")
{
d->properties[name] = QVariant(QByteArray::fromBase64(value.toAscii()));
}
else
d->properties[name] = value;
}
else
d->properties[e.attribute("name")] = QVariant(e.text());
}
}
n = n.nextSibling();
......@@ -92,6 +106,7 @@ void KisPropertiesConfiguration::toXML(QDomDocument& doc, QDomElement& root) con
QDomElement e = doc.createElement("param");
e.setAttribute("name", QString(it.key().toLatin1()));
QString type = "string";
QVariant v = it.value();
QDomText text;
if (v.type() == QVariant::UserType && v.userType() == qMetaTypeId<KisCubicCurve>()) {
......@@ -102,11 +117,18 @@ void KisPropertiesConfiguration::toXML(QDomDocument& doc, QDomElement& root) con
doc.appendChild(root);
v.value<KoColor>().toXML(doc, root);
text = doc.createCDATASection(doc.toString());
type = "color";
} else if(v.type() == QVariant::String ) {
text = doc.createCDATASection(v.toString()); // XXX: Unittest this!
type = "string";
} else if(v.type() == QVariant::ByteArray ) {
text = doc.createTextNode(QString::fromAscii(v.toByteArray().toBase64())); // Arbitary Data
type = "bytearray";
} else {
text = doc.createTextNode(v.toString());
type = "internal";
}
e.setAttribute("type", type);
e.appendChild(text);
root.appendChild(e);
}
......
......@@ -18,6 +18,7 @@
<description>
<p>Krita is the full-featured digital art studio.</p>
<p xml:lang="ca">Krita és l'estudi d'art digital ple de funcionalitats.</p>
<p xml:lang="de">Krita ist ein digitales Designstudio mit umfangreiche Funktionen</p>
<p xml:lang="fi">Krita on täysin varusteltu digitaalisen taiteen ateljee.</p>
<p xml:lang="ia">Krita es le studio de arte digital complete.</p>
<p xml:lang="nl">Krita is de digitale kunststudio vol mogelijkheden.</p>
......@@ -28,17 +29,16 @@
<p xml:lang="sv">Krita är den fullfjädrade digitala konststudion.</p>
<p xml:lang="uk">Krita — повноцінний комплекс для створення цифрових художніх творів.</p>
<p xml:lang="x-test">xxKrita is the full-featured digital art studio.xx</p>
<p>It is perfect for sketching and painting, and presets an end–to–end solution for creating digital painting files from scratch by masters..</p>
<p>It is perfect for sketching and painting, and presets an end–to–end solution for creating digital painting files from scratch by masters.</p>
<p xml:lang="ca">És perfecte per fer esbossos i pintar, i predefineix una solució final per crear fitxers de dibuix digital des de zero per a mestres.</p>
<p xml:lang="ia">Illo es perfecte pro schizzar e pinger, e prefixa un solution ab initio al fin pro crear files de pictura digital ab grattamentos per maestros.</p>
<p xml:lang="nl">Het is perfect voor schetsen en schilderen en zet een end–to–end oplossing voor het maken van digitale bestanden voor schilderingen vanuit het niets door meesters.</p>
<p xml:lang="pl">Nadaje się perfekcyjnie do szkicowania i malowania i dostarcza zupełnego rozwiązania dla tworzenia plików malowideł cyfrowych od zalążka.</p>
<p xml:lang="pt">É perfeito para desenhos e pinturas, oferecendo uma solução final para criar ficheiros de pintura digital do zero por mestres..</p>
<p xml:lang="pt-BR">É perfeito para desenhos e pinturas, oferecendo uma solução final para criar arquivos de desenho digital feitos a partir do zero por mestres...</p>
<p xml:lang="pt">É perfeito para desenhos e pinturas, oferecendo uma solução final para criar ficheiros de pintura digital do zero por mestres.</p>
<p xml:lang="pt-BR">É perfeito para desenhos e pinturas, oferecendo uma solução final para criar arquivos de desenho digital feitos a partir do zero por mestres.</p>