diff --git a/krita/pics/svg/dark_brush_ratio.svg b/krita/pics/svg/dark_brush_ratio.svg new file mode 100644 index 0000000000..c82751844f --- /dev/null +++ b/krita/pics/svg/dark_brush_ratio.svg @@ -0,0 +1,82 @@ + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + diff --git a/krita/pics/svg/dark_brush_rotation.svg b/krita/pics/svg/dark_brush_rotation.svg new file mode 100644 index 0000000000..592eebba9a --- /dev/null +++ b/krita/pics/svg/dark_brush_rotation.svg @@ -0,0 +1,86 @@ + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + diff --git a/krita/pics/svg/dark_brush_size.svg b/krita/pics/svg/dark_brush_size.svg new file mode 100644 index 0000000000..dc2c89c629 --- /dev/null +++ b/krita/pics/svg/dark_brush_size.svg @@ -0,0 +1,81 @@ + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + diff --git a/krita/pics/svg/light_brush_ratio.svg b/krita/pics/svg/light_brush_ratio.svg new file mode 100644 index 0000000000..0f368422d0 --- /dev/null +++ b/krita/pics/svg/light_brush_ratio.svg @@ -0,0 +1,82 @@ + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + diff --git a/krita/pics/svg/light_brush_rotation.svg b/krita/pics/svg/light_brush_rotation.svg new file mode 100644 index 0000000000..e82f1a7c49 --- /dev/null +++ b/krita/pics/svg/light_brush_rotation.svg @@ -0,0 +1,86 @@ + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + diff --git a/krita/pics/svg/light_brush_size.svg b/krita/pics/svg/light_brush_size.svg new file mode 100644 index 0000000000..e4baa5e27e --- /dev/null +++ b/krita/pics/svg/light_brush_size.svg @@ -0,0 +1,81 @@ + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + diff --git a/krita/pics/svg/svg-icons.qrc b/krita/pics/svg/svg-icons.qrc index 312f78b568..a163ad11ba 100644 --- a/krita/pics/svg/svg-icons.qrc +++ b/krita/pics/svg/svg-icons.qrc @@ -1,150 +1,156 @@ broken-preset.svgz dark_addblankframe.svg dark_addcolor.svg dark_addduplicateframe.svg + dark_brush_size.svg + dark_brush_rotation.svg + dark_brush_ratio.svg dark_deletekeyframe.svg dark_docker_lock_a.svg dark_docker_lock_b.svg dark_layer-locked.svg dark_layer-unlocked.svg dark_nextframe.svg dark_nextkeyframe.svg dark_lastframe.svg dark_prevkeyframe.svg dark_firstframe.svg dark_pallete_librarysvg.svg dark_passthrough-disabled.svg dark_passthrough-enabled.svg dark_prevframe.svg dark_selection-mode_ants.svg dark_selection-mode_invisible.svg dark_selection-mode_mask.svg dark_transparency-disabled.svg dark_transparency-enabled.svg dark_trim-to-image.svg delete.svgz layer-style-disabled.svg layer-style-enabled.svg light_addblankframe.svg light_addcolor.svg light_addduplicateframe.svg + light_brush_size.svg + light_brush_rotation.svg + light_brush_ratio.svg light_deletekeyframe.svg light_docker_lock_a.svg light_docker_lock_b.svg light_layer-locked.svg light_layer-unlocked.svg light_nextframe.svg light_pallete_library.svg light_passthrough-disabled.svgz light_passthrough-enabled.svgz light_prevframe.svg light_nextkeyframe.svg light_lastframe.svg light_prevkeyframe.svg light_firstframe.svg light_selection-mode_ants.svg light_selection-mode_invisible.svg light_selection-mode_mask.svg light_timeline_keyframe.svg light_transparency-disabled.svg light_transparency-enabled.svg light_trim-to-image.svg paintop_presets_disabled.svgz paintop_settings_01.svgz selection-info.svg selection-mode_invisible.svg svg-icons.qrc transparency-locked.svg transparency-unlocked.svg workspace-chooser.svg light_lazyframeOn.svg light_lazyframeOff.svg dark_lazyframeOn.svg dark_lazyframeOff.svg dark_mirror-view.svg light_mirror-view.svg dark_rotation-reset.svg light_rotation-reset.svg light_smoothing-basic.svg light_smoothing-no.svg light_smoothing-stabilizer.svg light_smoothing-weighted.svg dark_smoothing-basic.svg dark_smoothing-no.svg dark_smoothing-stabilizer.svg dark_smoothing-weighted.svg light_merge-layer-below.svg dark_merge-layer-below.svg light_rotate-canvas-left.svg light_rotate-canvas-right.svg dark_rotate-canvas-left.svg dark_rotate-canvas-right.svg light_gmic.svg dark_gmic.svg light_split-layer.svg dark_split-layer.svg light_color-to-alpha.svg dark_color-to-alpha.svg light_preset-switcher.svg dark_preset-switcher.svg dark_animation_play.svg dark_animation_stop.svg dark_dropframe.svg dark_droppedframes.svg light_animation_play.svg light_animation_stop.svg light_dropframe.svg light_droppedframes.svg dark_landscape.svg dark_portrait.svg light_landscape.svg light_portrait.svg dark_interpolation_constant.svg dark_interpolation_linear.svg dark_interpolation_bezier.svg dark_interpolation_sharp.svg dark_interpolation_smooth.svg light_interpolation_bezier.svg light_interpolation_constant.svg light_interpolation_linear.svg light_interpolation_sharp.svg light_interpolation_smooth.svg dark_audio-none.svg dark_audio-volume-high.svg dark_audio-volume-mute.svg dark_keyframe-add.svg dark_keyframe-remove.svg dark_zoom-fit.svg dark_zoom-horizontal.svg dark_zoom-vertical.svg light_audio-none.svg light_audio-volume-high.svg light_audio-volume-mute.svg light_keyframe-add.svg light_keyframe-remove.svg light_zoom-fit.svg light_zoom-horizontal.svg light_zoom-vertical.svg dark_showColoring.svg dark_showMarks.svg dark_showColoringOff.svg dark_showMarksOff.svg dark_updateColorize.svg light_showColoring.svg light_showMarks.svg light_showColoringOff.svg light_showMarksOff.svg light_updateColorize.svg diff --git a/plugins/tools/karbonplugins/tools/CalligraphyTool/KarbonCalligraphyOptionWidget.cpp b/plugins/tools/karbonplugins/tools/CalligraphyTool/KarbonCalligraphyOptionWidget.cpp index b623b96154..2b725cd15a 100644 --- a/plugins/tools/karbonplugins/tools/CalligraphyTool/KarbonCalligraphyOptionWidget.cpp +++ b/plugins/tools/karbonplugins/tools/CalligraphyTool/KarbonCalligraphyOptionWidget.cpp @@ -1,443 +1,445 @@ /* This file is part of the KDE project Copyright (C) 2008 Fela Winkelmolen This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "KarbonCalligraphyOptionWidget.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "kis_double_parse_spin_box.h" #include "kis_int_parse_spin_box.h" #include "ui_karboncalligraphytooloptions.h" #include "kis_slider_spin_box.h" /* Profiles are saved in karboncalligraphyrc In the group "General", profile is the name of profile used Every profile is described in a group, the name of which is "ProfileN" Starting to count from 0 onwards (NOTE: the index in profiles is different from the N) Default profiles are added by the function addDefaultProfiles(), once they have been added, the entry defaultProfilesAdded in the "General" group is set to true TODO: add a reset defaults option? */ // name of the configuration file const QString RCFILENAME = "karboncalligraphyrc"; class KarbonCalligraphyToolOptions: public QWidget, public Ui::WdgCalligraphyToolOptions { public: KarbonCalligraphyToolOptions(QWidget *parent = 0) : QWidget(parent) { setupUi(this); } }; KarbonCalligraphyOptionWidget::KarbonCalligraphyOptionWidget() : m_changingProfile(false) { m_options = new KarbonCalligraphyToolOptions(); m_options->setupUi(this); m_options->sldDistanceInterval->setPrefix(i18n("Distance: ")); //the distance is in SCREEN coordinates! m_options->sldDistanceInterval->setSuffix(i18n("px")); m_options->sldDistanceInterval->setRange(1, 1000, 2); m_options->sldDistanceInterval->setSingleStep(1); m_options->sldTimeInterval->setPrefix(i18n("Time: ")); m_options->sldTimeInterval->setSuffix(i18n("ms")); m_options->sldTimeInterval->setRange(1, 1000, 2); m_options->sldTimeInterval->setSingleStep(1); m_options->sldCaps->setPrefix(i18n("Caps: ")); m_options->sldCaps->setRange(0.0, 2.0, 2); m_options->sldCaps->setSingleStep(0.03); - m_options->tabRatio->setVisible(false); + m_options->tabWidget->setTabIcon(0, kisIcon("brush_size")); + m_options->tabWidget->setTabIcon(1, kisIcon("brush_rotation")); + m_options->tabWidget->setTabIcon(2, kisIcon("brush_ratio")); createConnections(); addDefaultProfiles(); // if they are already added does nothing loadProfiles(); } KarbonCalligraphyOptionWidget::~KarbonCalligraphyOptionWidget() { qDeleteAll(m_profiles); } void KarbonCalligraphyOptionWidget::emitAll() { emit usePathChanged(m_options->rdAdjustPath->isChecked()); emit capsChanged(m_options->sldCaps->value()); emit smoothTimeChanged(m_options->sldTimeInterval->value()); emit smoothDistanceChanged(m_options->sldDistanceInterval->value()); } void KarbonCalligraphyOptionWidget::loadProfile(const QString &name) { if (m_changingProfile) { return; } // write the new profile in the config file KConfig config(RCFILENAME); KConfigGroup generalGroup(&config, "General"); generalGroup.writeEntry("profile", name); config.sync(); // and load it loadCurrentProfile(); // don't show Current if it isn't selected if (name != i18n("Current")) { removeProfile(i18n("Current")); } } void KarbonCalligraphyOptionWidget::updateCurrentProfile() { if (!m_changingProfile) { saveProfile("Current"); } } void KarbonCalligraphyOptionWidget::saveProfileAs() { QString name; // loop until a valid name is entered or the user cancelled while (1) { bool ok; name = QInputDialog::getText(this, i18n("Profile name"), i18n("Please insert the name by which " "you want to save this profile:"), QLineEdit::Normal, QString(), &ok); if (!ok) { return; } if (name.isEmpty() || name == i18n("Current")) { KMessageBox::sorry(this, i18n("Sorry, the name you entered is invalid."), i18nc("invalid profile name", "Invalid name.")); // try again saveProfileAs(); continue; // ask again } if (m_profiles.contains(name)) { int ret = KMessageBox::warningYesNo(this, i18n("A profile with that name already exists.\n" "Do you want to overwrite it?")); if (ret == KMessageBox::Yes) { break; // exit while loop (save profile) } // else ask again } else { // the name is valid break; // exit while loop (save profile) } } saveProfile(name); } void KarbonCalligraphyOptionWidget::removeProfile() { removeProfile(m_options->cmbProfiles->currentText()); } /****************************************************************************** ************************* Convenience Functions ****************************** ******************************************************************************/ void KarbonCalligraphyOptionWidget::createConnections() { connect(m_options->cmbProfiles, SIGNAL(currentIndexChanged(QString)), SLOT(loadProfile(QString))); // propagate changes connect(m_options->rdAdjustPath, SIGNAL(toggled(bool)), SIGNAL(usePathChanged(bool))); connect(m_options->rdAdjustAssistant, SIGNAL(toggled(bool)), SIGNAL(useAssistantChanged(bool))); connect(m_options->rdNoAdjust, SIGNAL(toggled(bool)), SIGNAL(useNoAdjustChanged(bool))); connect(m_options->sldCaps, SIGNAL(valueChanged(double)), SIGNAL(capsChanged(double))); connect(m_options->sldTimeInterval, SIGNAL(valueChanged(double)), SIGNAL(smoothTimeChanged(double))); connect(m_options->sldDistanceInterval, SIGNAL(valueChanged(double)), SIGNAL(smoothDistanceChanged(double))); // update profile connect(m_options->rdAdjustPath, SIGNAL(toggled(bool)), SLOT(updateCurrentProfile())); connect(m_options->rdAdjustAssistant, SIGNAL(toggled(bool)), SLOT(updateCurrentProfile())); connect(m_options->rdNoAdjust, SIGNAL(toggled(bool)), SLOT(updateCurrentProfile())); connect(m_options->sldCaps, SIGNAL(valueChanged(double)), SLOT(updateCurrentProfile())); connect(m_options->sldTimeInterval, SIGNAL(valueChanged(double)), SLOT(updateCurrentProfile())); connect(m_options->sldDistanceInterval, SIGNAL(valueChanged(double)), SLOT(updateCurrentProfile())); connect(m_options->bnSaveProfile, SIGNAL(clicked()), SLOT(saveProfileAs())); connect(m_options->bnRemoveProfile, SIGNAL(clicked()), SLOT(removeProfile())); // visualization //connect(m_useAngle, SIGNAL(toggled(bool)), SLOT(toggleUseAngle(bool))); } void KarbonCalligraphyOptionWidget::addDefaultProfiles() { // check if the profiles where already added KConfig config(RCFILENAME); KConfigGroup generalGroup(&config, "General"); if (generalGroup.readEntry("defaultProfilesAdded", false)) { return; } KConfigGroup profile0(&config, "Profile0"); profile0.writeEntry("name", i18n("Mouse")); profile0.writeEntry("usePath", false); KConfigGroup profile1(&config, "Profile1"); profile1.writeEntry("name", i18n("Graphics Pen")); profile1.writeEntry("usePath", false); generalGroup.writeEntry("profile", i18n("Mouse")); generalGroup.writeEntry("defaultProfilesAdded", true); config.sync(); } void KarbonCalligraphyOptionWidget::loadProfiles() { KConfig config(RCFILENAME); // load profiles as long as they are present int i = 0; while (1) { // forever KConfigGroup profileGroup(&config, "Profile" + QString::number(i)); // invalid profile, assume we reached the last one if (!profileGroup.hasKey("name")) { break; } Profile *profile = new Profile; profile->index = i; profile->name = profileGroup.readEntry("name", QString()); profile->usePath = profileGroup.readEntry("usePath", false); profile->useAssistants = profileGroup.readEntry("useAssistants", false); profile->caps = profileGroup.readEntry("caps", 0.0); profile->timeInterval = profileGroup.readEntry("timeInterval", 0.0); profile->distanceInterval = profileGroup.readEntry("distanceInterval", 0.0); m_profiles.insert(profile->name, profile); ++i; } m_changingProfile = true; ProfileMap::const_iterator it = m_profiles.constBegin(); ProfileMap::const_iterator lastIt = m_profiles.constEnd(); for (; it != lastIt; ++it) { m_options->cmbProfiles->addItem(it.key()); } m_changingProfile = false; loadCurrentProfile(); } void KarbonCalligraphyOptionWidget::loadCurrentProfile() { KConfig config(RCFILENAME); KConfigGroup generalGroup(&config, "General"); QString currentProfile = generalGroup.readEntry("profile", QString()); // find the index needed by the comboBox int index = profilePosition(currentProfile); if (currentProfile.isEmpty() || index < 0) { return; } m_options->cmbProfiles->setCurrentIndex(index); Profile *profile = m_profiles[currentProfile]; m_changingProfile = true; m_options->rdAdjustPath->setChecked(profile->usePath); m_options->rdAdjustAssistant->setChecked(profile->useAssistants); if (profile->useAssistants == false && profile->usePath==false) { m_options->rdNoAdjust->setChecked(true); } m_options->sldCaps->setValue(profile->caps); m_options->sldTimeInterval->setValue(profile->timeInterval); m_options->sldDistanceInterval->setValue(profile->distanceInterval); m_changingProfile = false; } void KarbonCalligraphyOptionWidget::saveProfile(const QString &name) { Profile *profile = new Profile; profile->name = name; profile->usePath = m_options->rdAdjustPath->isChecked(); profile->caps = m_options->sldCaps->value(); profile->useAssistants = m_options->rdAdjustAssistant->isChecked(); profile->timeInterval = m_options->sldTimeInterval->value(); profile->distanceInterval = m_options->sldDistanceInterval->value(); if (m_profiles.contains(name)) { // there is already a profile with the same name, overwrite profile->index = m_profiles[name]->index; m_profiles.insert(name, profile); } else { // it is a new profile profile->index = m_profiles.count(); m_profiles.insert(name, profile); // add the profile to the combobox QString dbg; for (int i = 0; i < m_options->cmbProfiles->count(); ++i) { dbg += m_options->cmbProfiles->itemText(i) + ' '; } int pos = profilePosition(name); m_changingProfile = true; m_options->cmbProfiles->insertItem(pos, name); m_changingProfile = false; for (int i = 0; i < m_options->cmbProfiles->count(); ++i) { dbg += m_options->cmbProfiles->itemText(i) + ' '; } } KConfig config(RCFILENAME); QString str = "Profile" + QString::number(profile->index); KConfigGroup profileGroup(&config, str); profileGroup.writeEntry("name", name); profileGroup.writeEntry("usePath", profile->usePath); profileGroup.writeEntry("useAssistants", profile->useAssistants); profileGroup.writeEntry("caps", profile->caps); profileGroup.writeEntry("timeInterval", profile->timeInterval); profileGroup.writeEntry("distanceInterval", profile->distanceInterval); KConfigGroup generalGroup(&config, "General"); generalGroup.writeEntry("profile", name); config.sync(); m_options->cmbProfiles->setCurrentIndex(profilePosition(name)); } void KarbonCalligraphyOptionWidget::removeProfile(const QString &name) { int index = profilePosition(name); if (index < 0) { return; // no such profile } // remove the file from the config file KConfig config(RCFILENAME); int deletedIndex = m_profiles[name]->index; QString deletedGroup = "Profile" + QString::number(deletedIndex); config.deleteGroup(deletedGroup); config.sync(); // and from profiles m_profiles.remove(name); m_options->cmbProfiles->removeItem(index); // now in the config file there is value ProfileN missing, // where N = configIndex, so put the last one there if (m_profiles.isEmpty()) { return; } int lastN = -1; Profile *profile = 0; // profile to be moved, will be the last one Q_FOREACH (Profile *p, m_profiles) { if (p->index > lastN) { lastN = p->index; profile = p; } } Q_ASSERT(profile != 0); // do nothing if the deleted group was the last one if (deletedIndex > lastN) { return; } QString lastGroup = "Profile" + QString::number(lastN); config.deleteGroup(lastGroup); KConfigGroup profileGroup(&config, deletedGroup); profileGroup.writeEntry("name", name); profileGroup.writeEntry("usePath", profile->usePath); profileGroup.writeEntry("useAssistants", profile->useAssistants); profileGroup.writeEntry("caps", profile->caps); profileGroup.writeEntry("timeInterval", profile->timeInterval); profileGroup.writeEntry("distanceInterval", profile->distanceInterval); config.sync(); profile->index = deletedIndex; } int KarbonCalligraphyOptionWidget::profilePosition(const QString &profileName) { int res = 0; ProfileMap::const_iterator it = m_profiles.constBegin(); ProfileMap::const_iterator lastIt = m_profiles.constEnd(); for (; it != lastIt; ++it) { if (it.key() == profileName) { return res; } ++res; } return -1; } diff --git a/plugins/tools/karbonplugins/tools/CalligraphyTool/karboncalligraphytooloptions.ui b/plugins/tools/karbonplugins/tools/CalligraphyTool/karboncalligraphytooloptions.ui index 90bdfb6b74..a6464fbf9f 100644 --- a/plugins/tools/karbonplugins/tools/CalligraphyTool/karboncalligraphytooloptions.ui +++ b/plugins/tools/karbonplugins/tools/CalligraphyTool/karboncalligraphytooloptions.ui @@ -1,154 +1,163 @@ WdgCalligraphyToolOptions 0 0 400 - 369 + 385 Form Tool Presets Save profile as... ... .. Remove profile ... .. - 3 + 2 + + + - Size + + + + - Angle + + + + - Ratio + Adjustment Adjust Position No adjustment Follow Selected Path Follow Assistants Sampling Interval <html><head/><body><p>The Time Interval samples based on the time it takes to make the stroke. The value is in milliseconds.</p></body></html> The Distance interval samples based on the length of the stroke in the coordinates of the screen. So if you zoom in, you can make preciser strokes despite having the same distance interval. KisDoubleSliderSpinBox QWidget
kis_slider_spin_box.h
1