1
2
3 #include "toonz/studiopalette.h"
4 #include "tfiletype.h"
5 #include "tstream.h"
6 #include "tconvert.h"
7 #include "tlevel_io.h"
8 #include "trasterimage.h"
9 #include "traster.h"
10 #include "tsystem.h"
11 #include "tcolorstyles.h"
12 #include "toonz/toonzfolders.h"
13 #include "toonz/tproject.h"
14 #include "toonz/toonzscene.h"
15 #include "tpalette.h"
16
17 #include <time.h>
18 #include <stdio.h>
19 #include <sys/types.h>
20 #include <string.h>
21
22 #include <QSettings>
23
24 //===================================================================
25
26 //-------------------------------------------------------------------
27 namespace {
28 //-------------------------------------------------------------------
29
makeUniqueName(TFilePath fp)30 TFilePath makeUniqueName(TFilePath fp) {
31 if (TFileStatus(fp).doesExist() == false) return fp;
32 std::wstring name = fp.getWideName();
33 int index = 2;
34 int j = name.find_last_not_of(L"0123456789");
35 if (j != (int)std::wstring::npos && j + 1 < (int)name.length()) {
36 index = std::stoi(name.substr(j + 1)) + 1;
37 name = name.substr(0, j + 1);
38 }
39 for (;;) {
40 fp = fp.withName(name + std::to_wstring(index));
41 if (TFileStatus(fp).doesExist() == false) return fp;
42 index++;
43 }
44 }
45
46 //-------------------------------------------------------------------
47
loadPliPalette(const TFilePath & fp)48 TPalette *loadPliPalette(const TFilePath &fp) {
49 TLevelReaderP lr(fp);
50 TLevelP level = lr->loadInfo();
51 int frameCount = level->getFrameCount();
52 if (frameCount < 1) return 0;
53 TPalette *palette = level->getPalette();
54 if (!palette) return 0;
55 return palette->clone();
56 }
57
58 //-------------------------------------------------------------------
59
loadTplPalette(const TFilePath & fp)60 TPalette *loadTplPalette(const TFilePath &fp) {
61 TPersist *p = 0;
62 TIStream is(fp);
63 is >> p;
64 TPalette *palette = dynamic_cast<TPalette *>(p);
65 return palette;
66 }
67
68 //-------------------------------------------------------------------
69
loadToonz46Palette(const TFilePath & fp)70 TPalette *loadToonz46Palette(const TFilePath &fp) {
71 TImageP pltImg;
72 TImageReader::load(fp, pltImg);
73 if (!pltImg) return 0;
74 TRasterImageP pltRasImg(pltImg);
75 if (!pltRasImg) return 0;
76 TRaster32P rasPlt = pltRasImg->getRaster();
77 if (!rasPlt) return 0;
78 TPalette *palette = new TPalette();
79 const int offset = 0; // FirstUserStyle-1;
80 assert(rasPlt->getLy() == 2);
81 rasPlt->lock();
82 TPixel32 *pixelRow = rasPlt->pixels(0);
83 int x;
84 for (x = 1; x < rasPlt->getLx(); ++x) {
85 TPixel32 color = pixelRow[x];
86 int styleId = offset + x;
87 if (styleId < palette->getStyleCount())
88 palette->setStyle(styleId, color);
89 else {
90 int j = palette->addStyle(color);
91 assert(j == styleId);
92 }
93 }
94
95 // aggiungo solo i colori usati (salvo il BG)
96
97 pixelRow = rasPlt->pixels(1);
98 TPalette::Page *page = palette->getPage(0);
99 for (x = 1; x < rasPlt->getLx(); ++x) {
100 if (pixelRow[x].r == 255)
101 page->addStyle(offset +
102 x); // palette->addStyleToPage(offset+x, L"colors");
103 }
104 rasPlt->unlock();
105 return palette;
106 }
107
108 //-------------------------------------------------------------------
109
readPaletteGlobalName(TFilePath path)110 std::wstring readPaletteGlobalName(TFilePath path) {
111 try {
112 TIStream is(path);
113 if (!is) return L"";
114 std::string tagName;
115 if (!is.matchTag(tagName) || tagName != "palette") return L"";
116 std::string name;
117 if (is.getTagParam("name", name)) return ::to_wstring(name);
118 } catch (...) {
119 }
120 return L"";
121 }
122 //-------------------------------------------------------------------
123
searchPalette(TFilePath path,std::wstring paletteId)124 TFilePath searchPalette(TFilePath path, std::wstring paletteId) {
125 TFilePathSet q;
126 try {
127 TSystem::readDirectory(q, path);
128 } catch (...) {
129 }
130
131 for (TFilePathSet::iterator i = q.begin(); i != q.end(); ++i) {
132 TFilePath fp = *i;
133 if (fp.getType() == "tpl") {
134 std::wstring gname = readPaletteGlobalName(fp);
135 if (gname == paletteId) return fp;
136 } else if (TFileStatus(fp).isDirectory()) {
137 TFilePath palettePath = searchPalette(fp, paletteId);
138 if (palettePath != TFilePath()) return palettePath;
139 }
140 }
141 return TFilePath();
142 }
143
144 bool studioPaletteHasBeenReferred = false;
145
146 static std::map<std::wstring, TFilePath> table;
147 // table loaded from the cache. verify once before storing in the table
148 static std::map<std::wstring, TFilePath> table_cached;
149
150 const std::string pathTableFileName = "palette_paths.ini";
151
152 //-------------------------------------------------------------------
153 } // namespace
154 //-------------------------------------------------------------------
155
156 //===================================================================
157 //
158 // StudioPalette
159 //
160 //-------------------------------------------------------------------
161
StudioPalette()162 StudioPalette::StudioPalette() {
163 try {
164 m_root = ToonzFolder::getStudioPaletteFolder();
165 } catch (...) {
166 return;
167 }
168 if (!TFileStatus(m_root).doesExist()) {
169 try {
170 TSystem::mkDir(m_root);
171 FolderListenerManager::instance()->notifyFolderChanged(
172 m_root.getParentDir());
173 } catch (...) {
174 }
175 try {
176 TSystem::mkDir(getLevelPalettesRoot());
177 FolderListenerManager::instance()->notifyFolderChanged(
178 getLevelPalettesRoot().getParentDir());
179 } catch (...) {
180 }
181 }
182
183 // load [global id] - [path] table file
184 TFilePath rootFps[2] = {m_root, getProjectPalettesRoot()};
185 for (auto rootFp : rootFps) {
186 if (rootFp.isEmpty()) continue;
187 TFilePath tablePath = rootFp + pathTableFileName;
188 if (!TFileStatus(tablePath).doesExist()) continue;
189 QSettings tableSettings(QString::fromStdWString(tablePath.getWideString()),
190 QSettings::IniFormat);
191 for (auto key : tableSettings.allKeys())
192 table_cached[key.toStdWString()] =
193 rootFp + TFilePath(tableSettings.value(key, "").toString());
194 }
195 }
196
197 //-------------------------------------------------------------------
198
~StudioPalette()199 StudioPalette::~StudioPalette() {}
200
201 //-------------------------------------------------------------------
202
203 bool StudioPalette::m_enabled = true;
204
205 //-------------------------------------------------------------------
206
enable(bool enabled)207 void StudioPalette::enable(bool enabled) {
208 assert(studioPaletteHasBeenReferred == false);
209 m_enabled = enabled;
210 }
211
212 //-------------------------------------------------------------------
213
instance()214 StudioPalette *StudioPalette::instance() {
215 static StudioPalette _instance;
216 studioPaletteHasBeenReferred = true;
217 assert(m_enabled);
218 return &_instance;
219 }
220
221 //-------------------------------------------------------------------
222
getLevelPalettesRoot()223 TFilePath StudioPalette::getLevelPalettesRoot() {
224 return m_root + "Global Palettes";
225 }
226
227 //-------------------------------------------------------------------
228
getProjectPalettesRoot()229 TFilePath StudioPalette::getProjectPalettesRoot() {
230 TProjectP p = TProjectManager::instance()->getCurrentProject();
231 TFilePath folderName = p->getFolder(TProject::Palettes);
232 if (folderName.isEmpty()) return TFilePath();
233 if (folderName.isAbsolute()) return folderName;
234 return p->getProjectFolder() + folderName;
235 }
236
237 //-------------------------------------------------------------------
238
loadRefImg(TPalette * palette,TFilePath dir)239 static bool loadRefImg(TPalette *palette, TFilePath dir) {
240 assert(palette);
241 TFilePath fp = palette->getRefImgPath();
242 if (fp == TFilePath() || !TSystem::doesExistFileOrLevel(fp)) return false;
243 if (!fp.isAbsolute()) fp = dir + fp;
244 TLevelReaderP lr(fp);
245 if (!lr) return false;
246 TLevelP level = lr->loadInfo();
247 if (!level || level->getFrameCount() == 0) return false;
248 TLevel::Iterator it = level->begin();
249 TImageP img = lr->getFrameReader(it->first)->load();
250 if (!img) return false;
251 img->setPalette(0);
252 palette->setRefImg(img);
253 return true;
254 }
255
256 //-------------------------------------------------------------------
257
getPalette(const TFilePath & path,bool loadRefImgFlag)258 TPalette *StudioPalette::getPalette(const TFilePath &path,
259 bool loadRefImgFlag) {
260 try {
261 if (path.getType() != "tpl") return 0;
262 TPalette *palette = load(path);
263 if (!palette) return 0;
264 if (loadRefImgFlag) loadRefImg(palette, path.getParentDir());
265 // palette->addRef(); // ci va??
266 return palette;
267 } catch (...) {
268 return 0;
269 }
270 }
271
272 //-------------------------------------------------------------------
273
movePalette(const TFilePath & dstPath,const TFilePath & srcPath)274 void StudioPalette::movePalette(const TFilePath &dstPath,
275 const TFilePath &srcPath) {
276 try {
277 // do not allow overwrite palette
278 TSystem::renameFile(dstPath, srcPath, false);
279 } catch (...) {
280 throw;
281 }
282 std::wstring id = readPaletteGlobalName(dstPath);
283 table.erase(id);
284 removeEntry(id);
285 FolderListenerManager::instance()->notifyFolderChanged(
286 dstPath.getParentDir());
287 notifyMove(dstPath, srcPath);
288 }
289
290 //-------------------------------------------------------------------
291
getChildren(std::vector<TFilePath> & fps,const TFilePath & folderPath)292 int StudioPalette::getChildren(std::vector<TFilePath> &fps,
293 const TFilePath &folderPath) {
294 TFilePathSet q;
295 if (TFileStatus(folderPath).isDirectory()) {
296 try {
297 TSystem::readDirectory(q, folderPath, false, false);
298 } catch (...) {
299 }
300 }
301
302 // put the folders above the palette items
303 std::vector<TFilePath> palettes;
304 for (TFilePathSet::iterator i = q.begin(); i != q.end(); ++i) {
305 if (isFolder(*i))
306 fps.push_back(*i);
307 else if (isPalette(*i))
308 palettes.push_back(*i);
309 }
310 if (!palettes.empty()) {
311 fps.reserve(fps.size() + palettes.size());
312 std::copy(palettes.begin(), palettes.end(), std::back_inserter(fps));
313 }
314 // fps.push_back(m_root+"butta.tpl");
315 return fps.size();
316 }
317
318 //-------------------------------------------------------------------
319
getChildCount(const TFilePath & folderPath)320 int StudioPalette::getChildCount(const TFilePath &folderPath) {
321 TFilePathSet q;
322 try {
323 TSystem::readDirectory(q, folderPath);
324 } catch (...) {
325 }
326 return q.size();
327 }
328
329 //-------------------------------------------------------------------
330
isFolder(const TFilePath & path)331 bool StudioPalette::isFolder(const TFilePath &path) {
332 return TFileStatus(path).isDirectory();
333 }
334
335 //-------------------------------------------------------------------
336
isReadOnly(const TFilePath & path)337 bool StudioPalette::isReadOnly(const TFilePath &path) {
338 return !TFileStatus(path).isWritable();
339 }
340
341 //-------------------------------------------------------------------
342
isPalette(const TFilePath & path)343 bool StudioPalette::isPalette(const TFilePath &path) {
344 return path.getType() == "tpl";
345 }
346
347 //-------------------------------------------------------------------
348 /*! check if the palette is studio palette or level palette in order to separate
349 * icons in the StudioPaletteTree.
350 */
hasGlobalName(const TFilePath & path)351 bool StudioPalette::hasGlobalName(const TFilePath &path) {
352 return (readPaletteGlobalName(path) != L"");
353 }
354
355 //-------------------------------------------------------------------
356
isLevelPalette(const TFilePath & path)357 bool StudioPalette::isLevelPalette(const TFilePath &path) {
358 TPalette *palette = getPalette(path);
359 if (!palette) return false;
360 bool ret = !palette->isCleanupPalette();
361 delete palette;
362 return ret;
363 }
364
365 //-------------------------------------------------------------------
366
createFolder(const TFilePath & parentFolderPath)367 TFilePath StudioPalette::createFolder(const TFilePath &parentFolderPath) {
368 TFilePath path = makeUniqueName(parentFolderPath + "new folder");
369 try {
370 TSystem::mkDir(path);
371 } catch (...) {
372 return TFilePath();
373 }
374 FolderListenerManager::instance()->notifyFolderChanged(parentFolderPath);
375 notifyTreeChange();
376 return path;
377 }
378
379 //-------------------------------------------------------------------
380
createFolder(const TFilePath & parentFolderPath,std::wstring name)381 void StudioPalette::createFolder(const TFilePath &parentFolderPath,
382 std::wstring name) {
383 TFilePath fp = parentFolderPath + name;
384 if (TFileStatus(fp).doesExist()) return;
385 try {
386 TSystem::mkDir(fp);
387 } catch (...) {
388 return;
389 }
390 FolderListenerManager::instance()->notifyFolderChanged(parentFolderPath);
391 notifyTreeChange();
392 }
393
394 //-------------------------------------------------------------------
395
createPalette(const TFilePath & folderPath,std::string name)396 TFilePath StudioPalette::createPalette(const TFilePath &folderPath,
397 std::string name) {
398 TPalette *palette = 0;
399 if (name == "") name = "new palette";
400 palette = new TPalette();
401 TFilePath fp = makeUniqueName(folderPath + (name + ".tpl"));
402 time_t ltime;
403 time(<ime);
404 std::wstring gname = std::to_wstring(ltime) + L"_" + std::to_wstring(rand());
405 palette->setGlobalName(gname);
406 setStylesGlobalNames(palette);
407 try {
408 save(fp, palette);
409 } catch (...) {
410 delete palette;
411 throw;
412 }
413 delete palette;
414 notifyTreeChange();
415 return fp;
416 }
417
418 //-------------------------------------------------------------------
419
setPalette(const TFilePath & palettePath,const TPalette * plt,bool notifyPaletteChanged)420 void StudioPalette::setPalette(const TFilePath &palettePath,
421 const TPalette *plt, bool notifyPaletteChanged) {
422 assert(palettePath.getType() == "tpl");
423 TPalette *palette = plt->clone();
424 palette->setIsLocked(plt->isLocked());
425 palette->addRef();
426 std::wstring pgn = palette->getGlobalName();
427 if (TFileStatus(palettePath).doesExist())
428 pgn = readPaletteGlobalName(palettePath);
429 palette->setGlobalName(pgn);
430 setStylesGlobalNames(palette);
431 try {
432 save(palettePath, palette);
433 } catch (...) {
434 palette->release();
435 throw;
436 }
437 palette->release();
438 if (notifyPaletteChanged) notifyPaletteChange(palettePath);
439 }
440
441 //-------------------------------------------------------------------
442
deletePalette(const TFilePath & palettePath)443 void StudioPalette::deletePalette(const TFilePath &palettePath) {
444 assert(palettePath.getType() == "tpl");
445 try {
446 TSystem::deleteFile(palettePath);
447 } catch (...) {
448 return;
449 }
450 notifyTreeChange();
451 }
452
453 //-------------------------------------------------------------------
454
deleteFolder(const TFilePath & path)455 void StudioPalette::deleteFolder(const TFilePath &path) {
456 try {
457 TSystem::rmDirTree(path);
458 } catch (...) {
459 }
460 notifyTreeChange();
461 }
462
463 //-------------------------------------------------------------------
464
importPalette(const TFilePath & dstFolder,const TFilePath & srcPath)465 TFilePath StudioPalette::importPalette(const TFilePath &dstFolder,
466 const TFilePath &srcPath) {
467 TPaletteP palette;
468 std::string ext = srcPath.getType();
469 try {
470 if (ext == "plt")
471 palette = loadToonz46Palette(srcPath);
472 else if (ext == "pli")
473 palette = loadPliPalette(srcPath);
474 else if (ext == "tpl")
475 palette = loadTplPalette(srcPath);
476 } catch (...) {
477 }
478
479 if (!palette) return TFilePath();
480 std::wstring name = srcPath.getWideName();
481
482 assert(!palette->isCleanupPalette());
483 // convertToLevelPalette(palette.getPointer());
484
485 TFilePath fp = makeUniqueName(dstFolder + (name + L".tpl"));
486 time_t ltime;
487 time(<ime);
488 std::wstring gname = std::to_wstring(ltime) + L"_" + std::to_wstring(rand());
489 palette->setGlobalName(gname);
490 setStylesGlobalNames(palette.getPointer());
491 TSystem::touchParentDir(fp);
492 save(fp, palette.getPointer());
493 notifyTreeChange();
494 return fp;
495 }
496
497 //-------------------------------------------------------------------
498
499 // TFilePath StudioPalette::getRefImage(const TFilePath palette)
500 //{
501 // return palette.withType("pli");
502 //}
503
504 //-------------------------------------------------------------------
505
foobar(std::wstring paletteId)506 static void foobar(std::wstring paletteId) { table.erase(paletteId); }
507
getPalettePath(std::wstring paletteId)508 TFilePath StudioPalette::getPalettePath(std::wstring paletteId) {
509 std::map<std::wstring, TFilePath>::iterator it = table.find(paletteId);
510 if (it != table.end()) return it->second;
511 TFilePath fp;
512 // not found in the verified table, then check for the cached table
513 it = table_cached.find(paletteId);
514 // found in the cached table
515 if (it != table_cached.end()) {
516 fp = it->second;
517 // verify if cached path is correct
518 if (fp.getType() != "tpl" ||
519 readPaletteGlobalName(it->second) != paletteId) {
520 fp = TFilePath();
521 // erase the entry
522 it = table_cached.erase(it);
523 removeEntry(paletteId);
524 }
525 }
526 if (fp.isEmpty()) {
527 fp = searchPalette(m_root, paletteId);
528 if (fp.isEmpty()) fp = searchPalette(getProjectPalettesRoot(), paletteId);
529
530 addEntry(paletteId, fp);
531 }
532 table[paletteId] = fp;
533 return fp;
534 }
535
536 //-------------------------------------------------------------------
537
getPalette(std::wstring paletteId)538 TPalette *StudioPalette::getPalette(std::wstring paletteId) {
539 TFilePath palettePath = getPalettePath(paletteId);
540 if (palettePath != TFilePath())
541 return getPalette(palettePath);
542 else
543 return 0;
544 }
545
546 //-------------------------------------------------------------------
547
getStyle(std::wstring styleId)548 TColorStyle *StudioPalette::getStyle(std::wstring styleId) { return 0; }
549
550 //-------------------------------------------------------------------
551
getSourceStyle(TColorStyle * cs)552 std::pair<TFilePath, int> StudioPalette::getSourceStyle(TColorStyle *cs) {
553 std::pair<TFilePath, int> ret(TFilePath(), -1);
554 if (!cs) return ret;
555 std::wstring gname = cs->getGlobalName();
556 if (gname == L"") return ret;
557 int k = gname.find_first_of(L'-', 1);
558 if (k == (int)std::wstring::npos) return ret;
559 std::wstring paletteId = gname.substr(1, k - 1);
560 ret.first = getPalettePath(paletteId) - m_root;
561 ret.second = std::stoi(gname.substr(k + 1));
562 return ret;
563 }
564
565 //-------------------------------------------------------------------
566 /*! return if any style in the palette is changed
567 */
updateLinkedColors(TPalette * palette)568 bool StudioPalette::updateLinkedColors(TPalette *palette) {
569 bool paletteIsChanged = false;
570 std::map<std::wstring, TPaletteP> table;
571
572 for (int i = 0; i < palette->getStyleCount(); i++) {
573 TColorStyle *cs = palette->getStyle(i);
574 std::wstring gname = cs->getGlobalName();
575 if (gname == L"" || gname[0] != L'+') continue;
576 int k = gname.find_first_of(L'-', 1);
577 if (k == (int)std::wstring::npos) continue;
578 std::wstring paletteId = gname.substr(1, k - 1);
579 std::map<std::wstring, TPaletteP>::iterator it;
580 it = table.find(paletteId);
581 TPalette *spPalette = 0;
582 if (it == table.end()) {
583 spPalette = getPalette(paletteId);
584 if (!spPalette) continue;
585 table[paletteId] = spPalette;
586 // spPalette->release();
587 assert(spPalette->getRefCount() == 1);
588 } else
589 spPalette = it->second.getPointer();
590
591 int j = std::stoi(gname.substr(k + 1));
592 if (spPalette && 0 <= j && j < spPalette->getStyleCount()) {
593 TColorStyle *spStyle = spPalette->getStyle(j);
594 assert(spStyle);
595 spStyle = spStyle->clone();
596 spStyle->setGlobalName(gname);
597
598 // put the style name in the studio palette into the original name
599 spStyle->setOriginalName(spStyle->getName());
600 //.. and keep the style name unchanged
601 spStyle->setName(cs->getName());
602
603 palette->setStyle(i, spStyle);
604
605 paletteIsChanged = true;
606 }
607 }
608 return paletteIsChanged;
609 }
610
611 //-------------------------------------------------------------------
612
setStylesGlobalNames(TPalette * palette)613 void StudioPalette::setStylesGlobalNames(TPalette *palette) {
614 for (int i = 0; i < palette->getStyleCount(); i++) {
615 TColorStyle *cs = palette->getStyle(i);
616 // set global name only to the styles of which the global name is empty
617 if (cs->getGlobalName() == L"") {
618 std::wstring gname =
619 L"-" + palette->getGlobalName() + L"-" + std::to_wstring(i);
620 cs->setGlobalName(gname);
621 }
622 }
623 }
624
625 //-------------------------------------------------------------------
626
save(const TFilePath & path,TPalette * palette)627 void StudioPalette::save(const TFilePath &path, TPalette *palette) {
628 TFileStatus fs(path);
629 if (fs.doesExist() && !fs.isWritable()) {
630 throw TSystemException(path,
631 "The studio palette cannot be saved: it is a read "
632 "only studio palette.");
633 }
634
635 TOStream os(path);
636 if (!os) {
637 throw TSystemException(path,
638 "The studio palette cannot be saved: the output "
639 "stream status is invalid.");
640 }
641 std::map<std::string, std::string> attr;
642 attr["name"] = ::to_string(palette->getGlobalName());
643 os.openChild("palette", attr);
644 palette->saveData(os);
645 os.closeChild();
646 }
647
648 //-------------------------------------------------------------------
649
load(const TFilePath & path)650 TPalette *StudioPalette::load(const TFilePath &path) {
651 try {
652 TIStream is(path);
653 if (!is) return 0;
654 std::string tagName;
655 if (!is.matchTag(tagName) || tagName != "palette") return 0;
656 std::string gname;
657 is.getTagParam("name", gname);
658 TPalette *palette = new TPalette();
659 palette->loadData(is);
660 palette->setGlobalName(::to_wstring(gname));
661 is.matchEndTag();
662 palette->setPaletteName(path.getWideName());
663 return palette;
664 } catch (...) {
665 return 0;
666 }
667 }
668
669 //-------------------------------------------------------------------
670
addListener(Listener * listener)671 void StudioPalette::addListener(Listener *listener) {
672 if (std::find(m_listeners.begin(), m_listeners.end(), listener) ==
673 m_listeners.end())
674 m_listeners.push_back(listener);
675 }
676
677 //-------------------------------------------------------------------
678
removeListener(Listener * listener)679 void StudioPalette::removeListener(Listener *listener) {
680 m_listeners.erase(
681 std::remove(m_listeners.begin(), m_listeners.end(), listener),
682 m_listeners.end());
683 }
684
685 //-------------------------------------------------------------------
686
notifyTreeChange()687 void StudioPalette::notifyTreeChange() {
688 for (std::vector<Listener *>::iterator it = m_listeners.begin();
689 it != m_listeners.end(); ++it)
690 (*it)->onStudioPaletteTreeChange();
691 }
692
693 //-------------------------------------------------------------------
694
notifyMove(const TFilePath & dstPath,const TFilePath & srcPath)695 void StudioPalette::notifyMove(const TFilePath &dstPath,
696 const TFilePath &srcPath) {
697 for (std::vector<Listener *>::iterator it = m_listeners.begin();
698 it != m_listeners.end(); ++it)
699 (*it)->onStudioPaletteMove(dstPath, srcPath);
700 }
701
702 //-------------------------------------------------------------------
703
notifyPaletteChange(const TFilePath & palette)704 void StudioPalette::notifyPaletteChange(const TFilePath &palette) {
705 for (std::vector<Listener *>::iterator it = m_listeners.begin();
706 it != m_listeners.end(); ++it)
707 (*it)->onStudioPaletteChange(palette);
708 }
709
710 //-------------------------------------------------------------------
711
removeEntry(const std::wstring paletteId)712 void StudioPalette::removeEntry(const std::wstring paletteId) {
713 TFilePath rootFps[2] = {m_root, getProjectPalettesRoot()};
714 for (auto rootFp : rootFps) {
715 if (rootFp.isEmpty()) continue;
716 TFilePath tablePath = rootFp + pathTableFileName;
717 if (!TFileStatus(tablePath).doesExist()) continue;
718 QSettings tableSettings(QString::fromStdWString(tablePath.getWideString()),
719 QSettings::IniFormat);
720 if (tableSettings.contains(QString::fromStdWString(paletteId))) {
721 tableSettings.remove(QString::fromStdWString(paletteId));
722 break;
723 }
724 }
725 }
726
727 //-------------------------------------------------------------------
728
addEntry(const std::wstring paletteId,const TFilePath & path)729 void StudioPalette::addEntry(const std::wstring paletteId,
730 const TFilePath &path) {
731 TFilePath rootFps[2] = {m_root, getProjectPalettesRoot()};
732 for (auto rootFp : rootFps) {
733 if (rootFp.isEmpty()) continue;
734 if (!rootFp.isAncestorOf(path)) continue;
735
736 TFilePath tablePath = rootFp + pathTableFileName;
737 QSettings tableSettings(QString::fromStdWString(tablePath.getWideString()),
738 QSettings::IniFormat);
739 QString pathValue = (path - rootFp).getQString();
740 tableSettings.setValue(QString::fromStdWString(paletteId), pathValue);
741 }
742 }