File indexing completed on 2024-05-12 16:01:55
0001 /* This file is part of the KDE project 0002 SPDX-FileCopyrightText: 2000 Werner Trobin <trobin@kde.org> 0003 0004 SPDX-License-Identifier: LGPL-2.0-or-later 0005 */ 0006 0007 #include "KisTemplateTree.h" 0008 0009 #include <QDir> 0010 #include <QPrinter> 0011 #include <QUrl> 0012 0013 #include <kdesktopfile.h> 0014 #include <kconfig.h> 0015 #include <kis_debug.h> 0016 0017 0018 #include <KoResourcePaths.h> 0019 #include <klocalizedstring.h> 0020 #include <kconfiggroup.h> 0021 0022 #include <KisTemplate.h> 0023 #include <KisTemplateGroup.h> 0024 #include <KisTemplates.h> 0025 0026 static QString currentLocale() 0027 { 0028 const QStringList languages = KLocalizedString::languages(); 0029 if (languages.isEmpty()) { 0030 return QLocale().name(); 0031 } else { 0032 return languages.first(); 0033 } 0034 } 0035 0036 KisTemplateTree::KisTemplateTree(const QString &templatesResourcePath, 0037 bool readTree) 0038 : m_templatesResourcePath(templatesResourcePath) 0039 , m_defaultGroup(0) 0040 , m_defaultTemplate(0) 0041 { 0042 if (readTree) 0043 readTemplateTree(); 0044 } 0045 0046 KisTemplateTree::~KisTemplateTree() 0047 { 0048 qDeleteAll(m_groups); 0049 } 0050 0051 void KisTemplateTree::readTemplateTree() 0052 { 0053 readGroups(); 0054 readTemplates(); 0055 } 0056 0057 void KisTemplateTree::writeTemplateTree() 0058 { 0059 QString localDir = KoResourcePaths::saveLocation("templates"); 0060 0061 Q_FOREACH (KisTemplateGroup *group, m_groups) { 0062 //dbgUI <<"---------------------------------"; 0063 //dbgUI <<"group:" << group->name(); 0064 0065 bool touched = false; 0066 QList<KisTemplate*> templates = group->templates(); 0067 QList<KisTemplate*>::iterator it = templates.begin(); 0068 for (; it != templates.end() && !touched && !group->touched(); ++it) 0069 touched = (*it)->touched(); 0070 0071 if (group->touched() || touched) { 0072 //dbgUI <<"touched"; 0073 if (!group->isHidden()) { 0074 //dbgUI <<"not hidden"; 0075 QDir path; 0076 path.mkpath(localDir + group->name()); // create the local group dir 0077 } else { 0078 //dbgUI <<"hidden"; 0079 if (group->dirs().count() == 1 && group->dirs().contains(localDir)) { 0080 //dbgUI <<"local only"; 0081 QFile f(group->dirs().first()); 0082 f.remove(); 0083 //dbgUI <<"removing:" << group->dirs().first(); 0084 } else { 0085 //dbgUI <<"global"; 0086 QDir path; 0087 path.mkpath(localDir + group->name()); 0088 } 0089 } 0090 } 0091 Q_FOREACH (KisTemplate *t, templates) { 0092 if (t->touched()) { 0093 //dbgUI <<"++template:" << t->name(); 0094 writeTemplate(t, group, localDir); 0095 } 0096 if (t->isHidden() && t->touched()) { 0097 //dbgUI <<"+++ delete local template ##############"; 0098 writeTemplate(t, group, localDir); 0099 QFile::remove(t->file()); 0100 QFile::remove(t->picture()); 0101 } 0102 } 0103 } 0104 } 0105 0106 bool KisTemplateTree::add(KisTemplateGroup *g) 0107 { 0108 0109 KisTemplateGroup *group = find(g->name()); 0110 if (group == 0) { 0111 m_groups.append(g); 0112 return true; 0113 } 0114 0115 group->addDir(g->dirs().first()); // "...there can be only one..." (Queen) 0116 delete g; 0117 g = 0; 0118 return false; 0119 } 0120 0121 KisTemplateGroup *KisTemplateTree::find(const QString &name) const 0122 { 0123 QList<KisTemplateGroup*>::const_iterator it = m_groups.begin(); 0124 KisTemplateGroup* ret = 0; 0125 0126 while (it != m_groups.end()) { 0127 if ((*it)->name() == name) { 0128 ret = *it; 0129 break; 0130 } 0131 0132 ++it; 0133 } 0134 0135 return ret; 0136 } 0137 0138 void KisTemplateTree::readGroups() 0139 { 0140 0141 QStringList dirs = KoResourcePaths::findDirs("templates"); 0142 0143 Q_FOREACH (const QString & dirName, dirs) { 0144 if (!dirName.contains("templates")) continue; // Hack around broken KoResourcePaths 0145 QDir dir(dirName); 0146 // avoid the annoying warning 0147 if (!dir.exists()) 0148 continue; 0149 QStringList templateDirs = dir.entryList(QDir::Dirs | QDir::NoDotAndDotDot); 0150 0151 0152 Q_FOREACH (const QString & templateDirName, templateDirs) { 0153 QDir templateDir(dirName + "/" + templateDirName); 0154 QString name = templateDirName; 0155 QString defaultTab; 0156 int sortingWeight = 1000; 0157 if (templateDir.exists(".directory")) { 0158 KDesktopFile config(templateDir.absoluteFilePath(".directory")); 0159 config.setLocale(currentLocale()); 0160 KConfigGroup dg = config.desktopGroup(); 0161 name = dg.readEntry("Name"); 0162 defaultTab = dg.readEntry("X-KDE-DefaultTab"); 0163 sortingWeight = dg.readEntry("X-KDE-SortingWeight", 1000); 0164 } 0165 KisTemplateGroup *g = new KisTemplateGroup(name, templateDir.absolutePath() + '/', sortingWeight); 0166 if (add(g)) { 0167 if (defaultTab == "true") { 0168 m_defaultGroup = g; 0169 } 0170 } 0171 } 0172 } 0173 } 0174 0175 void KisTemplateTree::readTemplates() 0176 { 0177 QString dontShow = "imperial"; 0178 if ( QLocale().measurementSystem() == QLocale::ImperialSystem) { 0179 dontShow = "metric"; 0180 } 0181 0182 Q_FOREACH (KisTemplateGroup* group, m_groups) { 0183 QStringList dirs = group->dirs(); 0184 for (QStringList::ConstIterator it = dirs.constBegin(); it != dirs.constEnd(); ++it) { 0185 QDir d(*it); 0186 if (!d.exists()) 0187 continue; 0188 QStringList files = d.entryList(QDir::Files | QDir::Readable, QDir::Name); 0189 for (int i = 0; i < files.count(); ++i) { 0190 QString filePath = *it + files[i]; 0191 //dbgUI <<"filePath:" << filePath; 0192 QString icon; 0193 QString text; 0194 QString description; 0195 QString hidden_str; 0196 QString fileName; 0197 bool hidden = false; 0198 bool defaultTemplate = false; 0199 QString templatePath; 0200 QString measureSystem; 0201 // If a desktop file, then read the name from it. 0202 // Otherwise (or if no name in it?) use file name 0203 if (KDesktopFile::isDesktopFile(filePath)) { 0204 KConfig _config(filePath, KConfig::SimpleConfig); 0205 _config.setLocale(currentLocale()); 0206 KConfigGroup config(&_config, "Desktop Entry"); 0207 if (config.readEntry("Type") == "Link") { 0208 text = config.readEntry("Name"); 0209 fileName = filePath; 0210 description = config.readEntry("Comment"); 0211 //dbgUI <<"name:" << text; 0212 icon = config.readEntry("Icon"); 0213 if (icon[0] != '/' && // allow absolute paths for icons 0214 QFile::exists(*it + icon)) // allow icons from icontheme 0215 icon = *it + icon; 0216 //dbgUI <<"icon2:" << icon; 0217 hidden = config.readEntry("X-KDE-Hidden", false); 0218 defaultTemplate = config.readEntry("X-KDE-DefaultTemplate", false); 0219 measureSystem = config.readEntry("X-KDE-MeasureSystem").toLower(); 0220 0221 // Don't add a template that is for the wrong measure system 0222 if (measureSystem == dontShow) 0223 continue; 0224 0225 //dbgUI <<"hidden:" << hidden_str; 0226 templatePath = config.readPathEntry("URL", QString()); 0227 //dbgUI <<"Link to :" << templatePath; 0228 if (templatePath[0] != '/') { 0229 if (templatePath.left(6) == "file:/") // I doubt this will happen 0230 templatePath = templatePath.right(templatePath.length() - 6); 0231 //else 0232 // dbgUI <<"dirname=" << *it; 0233 templatePath = *it + templatePath; 0234 //dbgUI <<"templatePath:" << templatePath; 0235 } 0236 } else 0237 continue; // Invalid 0238 } 0239 // The else if and the else branch are here for compat. with the old system 0240 else if (files[i].right(4) != ".png") 0241 // Ignore everything that is not a PNG file 0242 continue; 0243 else { 0244 // Found a PNG file - the template must be here in the same dir. 0245 icon = filePath; 0246 QFileInfo fi(filePath); 0247 text = fi.completeBaseName(); 0248 templatePath = filePath; // Note that we store the .png file as the template ! 0249 // That's the way it's always been done. Then the app replaces the extension... 0250 } 0251 KisTemplate *t = new KisTemplate(text, description, templatePath, icon, fileName, 0252 measureSystem, hidden); 0253 group->add(t, false, false); // false -> we aren't a "user", false -> don't 0254 // "touch" the group to avoid useless 0255 // creation of dirs in .kde/blah/... 0256 if (defaultTemplate) 0257 m_defaultTemplate = t; 0258 } 0259 } 0260 } 0261 } 0262 0263 void KisTemplateTree::writeTemplate(KisTemplate *t, KisTemplateGroup *group, 0264 const QString &localDir) 0265 { 0266 QString fileName; 0267 if (t->isHidden()) { 0268 fileName = t->fileName(); 0269 // try to remove the file 0270 if (QFile::remove(fileName) || !QFile::exists(fileName)) { 0271 QFile::remove(t->name()); 0272 QFile::remove(t->picture()); 0273 return; 0274 } 0275 } 0276 // be sure that the template's file name is unique so we don't overwrite an other 0277 QString const path = localDir + group->name() + '/'; 0278 QString const name = KisTemplates::trimmed(t->name()); 0279 fileName = path + name + ".desktop"; 0280 if (t->isHidden() && QFile::exists(fileName)) 0281 return; 0282 QString fill; 0283 while (QFile(fileName).exists()) { 0284 fill += '_'; 0285 fileName = path + fill + name + ".desktop"; 0286 } 0287 0288 KConfig _config(fileName, KConfig::SimpleConfig); 0289 _config.setLocale(currentLocale()); 0290 KConfigGroup config(&_config, "Desktop Entry"); 0291 config.writeEntry("Type", "Link"); 0292 config.writePathEntry("URL", t->file()); 0293 config.writeEntry("Name", t->name()); 0294 config.writeEntry("Icon", t->picture()); 0295 config.writeEntry("X-KDE-Hidden", t->isHidden()); 0296 }