File indexing completed on 2024-05-12 05:14:55

0001 /*
0002  *  preferences.cpp  -  program preference settings
0003  *  Program:  kalarm
0004  *  SPDX-FileCopyrightText: 2001-2024 David Jarvie <djarvie@kde.org>
0005  *
0006  *  SPDX-License-Identifier: GPL-2.0-or-later
0007  */
0008 
0009 #include "preferences.h"
0010 
0011 #include "kalarm.h"
0012 #include "kamail.h"
0013 #include "pluginmanager.h"
0014 #include "lib/desktop.h"
0015 #include "lib/messagebox.h"
0016 #include "lib/shellprocess.h"
0017 #include "kalarmcalendar/holidays.h"
0018 #include "kalarmcalendar/identities.h"
0019 #include "kalarm_debug.h"
0020 
0021 #include <KIdentityManagementCore/Identity>
0022 #include <KIdentityManagementCore/IdentityManager>
0023 
0024 #include <KSharedConfig>
0025 #include <KConfigGroup>
0026 #include <KMessageBox>
0027 #include <KWindowSystem>
0028 #include <KShell>
0029 
0030 #include <QFile>
0031 #include <QSaveFile>
0032 #include <QDir>
0033 #include <QStandardPaths>
0034 
0035 #include <time.h>
0036 
0037 using namespace KAlarmCal;
0038 
0039 //clazy:excludeall=non-pod-global-static
0040 
0041 namespace
0042 {
0043 
0044 // Config file entry names
0045 const QLatin1String GENERAL_GROUP("General");
0046 
0047 // Config file entry name for temporary use
0048 const char* TEMP = "Temp";
0049 
0050 const QString AUTOSTART_FILE(QStringLiteral("kalarm.autostart.desktop"));
0051 
0052 // Values for EmailFrom entry
0053 const QString FROM_SYS_SETTINGS(QStringLiteral("@SystemSettings"));
0054 const QString FROM_KMAIL(QStringLiteral("@KMail"));
0055 
0056 // Command strings for executing commands in different types of terminal windows.
0057 // %t = window title parameter
0058 // %c = command to execute in terminal
0059 // %w = command to execute in terminal, with 'sleep 86400' appended
0060 // %C = temporary command file to execute in terminal
0061 // %W = temporary command file to execute in terminal, with 'sleep 86400' appended
0062 const QList<QString> xtermCommands {
0063     QStringLiteral("xterm -sb -hold -title %t -e %c"),
0064     QStringLiteral("konsole --noclose -p tabtitle=%t -e ${SHELL:-sh} -c %c"),
0065     QStringLiteral("gnome-terminal -t %t -e %W"),
0066     QStringLiteral("eterm --pause -T %t -e %C"),    // some systems use eterm...
0067     QStringLiteral("Eterm --pause -T %t -e %C"),    // while some use Eterm
0068     QStringLiteral("rxvt -title %t -e ${SHELL:-sh} -c %w"),
0069     QStringLiteral("xfce4-terminal -T %t -H -e %c")
0070 };
0071 
0072 QList<QString> xtermCommandExes;   // initialised to hold executables in xtermCommands
0073 
0074 void splitXTermCommands();
0075 
0076 } // namespace
0077 
0078 // Config file entry names for notification messages
0079 const QLatin1String Preferences::QUIT_WARN("QuitWarn");
0080 const QLatin1String Preferences::ASK_AUTO_START("AskAutoStart");
0081 const QLatin1String Preferences::CONFIRM_ALARM_DELETION("ConfirmAlarmDeletion");
0082 const QLatin1String Preferences::EMAIL_QUEUED_NOTIFY("EmailQueuedNotify");
0083 const bool  default_quitWarn             = true;
0084 const bool  default_emailQueuedNotify    = false;
0085 const bool  default_confirmAlarmDeletion = true;
0086 
0087 static QString translateXTermPath(const QString& cmdline, bool write);
0088 
0089 
0090 Preferences*         Preferences::mInstance = nullptr;
0091 bool                 Preferences::mUsingDefaults = false;
0092 Holidays*            Preferences::mHolidays = nullptr;   // always non-null after Preferences initialisation
0093 QString              Preferences::mPreviousVersion;
0094 Preferences::Backend Preferences::mPreviousBackend;
0095 // Change tracking
0096 bool           Preferences::mAutoStartChangedByUser = false;
0097 
0098 
0099 Preferences* Preferences::self()
0100 {
0101     if (!mInstance)
0102     {
0103         // Set the default button for the Quit warning message box to Cancel
0104         KAMessageBox::setContinueDefault(QUIT_WARN, KMessageBox::Cancel);
0105         KAMessageBox::setDefaultShouldBeShownContinue(QUIT_WARN, default_quitWarn);
0106         KAMessageBox::setDefaultShouldBeShownContinue(EMAIL_QUEUED_NOTIFY, default_emailQueuedNotify);
0107         KAMessageBox::setDefaultShouldBeShownContinue(CONFIRM_ALARM_DELETION, default_confirmAlarmDeletion);
0108 
0109         mInstance = new Preferences;
0110     }
0111     return mInstance;
0112 }
0113 
0114 Preferences::Preferences()
0115 {
0116     QObject::connect(this, &Preferences::base_StartOfDayChanged, this, &Preferences::startDayChange);
0117     QObject::connect(this, &Preferences::base_TimeZoneChanged, this, &Preferences::timeZoneChange);
0118     QObject::connect(this, &Preferences::base_HolidayRegionChanged, this, &Preferences::holidaysChange);
0119     QObject::connect(this, &Preferences::base_WorkTimeChanged, this, &Preferences::workTimeChange);
0120 
0121     load();
0122     // Fetch the KAlarm version and backend which wrote the previous config file
0123     mPreviousVersion = version();
0124     mPreviousBackend = backend();
0125     // Update the KAlarm version in the config file, but don't call
0126     // writeConfig() here - leave it to be written only if the config file
0127     // is updated with other data.
0128     setVersion(QStringLiteral(KALARM_VERSION));
0129 }
0130 
0131 /******************************************************************************
0132 * Get whether the Akonadi plugin should be used, if available.
0133 */
0134 bool Preferences::useAkonadi()
0135 {
0136     return self()->mUseAkonadiIfAvailable  &&  PluginManager::instance()->akonadiPlugin();
0137 }
0138 
0139 /******************************************************************************
0140 * Return the Akonadi plugin to use, or null if not being used or not available.
0141 */
0142 AkonadiPlugin* Preferences::akonadiPlugin()
0143 {
0144     if (!self()->mUseAkonadiIfAvailable)
0145         return nullptr;
0146     return PluginManager::instance()->akonadiPlugin();
0147 }
0148 
0149 void Preferences::setUseAkonadi(bool yes)
0150 {
0151     if (PluginManager::instance()->akonadiPlugin())
0152         self()->setUseAkonadiIfAvailable(yes);
0153 }
0154 
0155 /******************************************************************************
0156 * Auto hiding of the system tray icon is only allowed on desktops which provide
0157 * GUI controls to show hidden icons.
0158 */
0159 int Preferences::autoHideSystemTray()
0160 {
0161     if (noAutoHideSystemTrayDesktops().contains(Desktop::currentIdentityName()))
0162         return 0;   // never hide
0163     return self()->mBase_AutoHideSystemTray;
0164 }
0165 
0166 /******************************************************************************
0167 * Auto hiding of the system tray icon is only allowed on desktops which provide
0168 * GUI controls to show hidden icons, so while KAlarm is running on such a
0169 * desktop, don't allow changes to the setting.
0170 */
0171 void Preferences::setAutoHideSystemTray(int timeout)
0172 {
0173     if (noAutoHideSystemTrayDesktops().contains(Desktop::currentIdentityName()))
0174         return;
0175     self()->setBase_AutoHideSystemTray(timeout);
0176 }
0177 
0178 void Preferences::setAskAutoStart(bool yes)
0179 {
0180     KAMessageBox::saveDontShowAgainYesNo(ASK_AUTO_START, !yes);
0181 }
0182 
0183 /******************************************************************************
0184 * Set the NoAutoStart condition.
0185 * On KDE desktops, the "X-KDE-autostart-condition" entry in
0186 * kalarm.autostart.desktop references this to determine whether to autostart KAlarm.
0187 * On non-KDE desktops, the "X-KDE-autostart-condition" entry in
0188 * kalarm.autostart.desktop doesn't have any effect, so that KAlarm will be
0189 * autostarted even if it is set not to autostart. Adding a "Hidden" entry to,
0190 * and removing the "OnlyShowIn=KDE" entry from, a user-modifiable copy of the
0191 * file fixes this.
0192 */
0193 void Preferences::setNoAutoStart(bool yes)
0194 {
0195     // Find the existing kalarm.autostart.desktop file, and whether it's writable.
0196     bool existingRO = true;   // whether the existing file is read-only
0197     QString autostartFile;
0198     QString configDirRW;
0199     const QStringList autostartDirs = QStandardPaths::standardLocations(QStandardPaths::GenericConfigLocation);
0200     for (const QString& dir : autostartDirs)
0201     {
0202         const QString file = dir + QLatin1String("/autostart/") + AUTOSTART_FILE;
0203         if (QFile::exists(file))
0204         {
0205             QFileInfo info(file);
0206             if (info.isReadable())
0207             {
0208                 autostartFile = file;
0209                 existingRO = !info.isWritable();
0210                 if (!existingRO)
0211                     configDirRW = dir;
0212                 break;
0213             }
0214         }
0215     }
0216 
0217     // If the existing file isn't writable, find the path to create a writable copy
0218     QString autostartFileRW = autostartFile;
0219     if (existingRO)
0220     {
0221         configDirRW = QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation);
0222         autostartFileRW = configDirRW + QLatin1String("/autostart/") + AUTOSTART_FILE;
0223         if (configDirRW.isEmpty())
0224         {
0225             qCWarning(KALARM_LOG) << "Preferences::setNoAutoStart: No writable autostart file path";
0226             return;
0227         }
0228         if (QFile::exists(autostartFileRW))
0229         {
0230             QFileInfo info(autostartFileRW);
0231             if (!info.isReadable() || !info.isWritable())
0232             {
0233                 qCWarning(KALARM_LOG) << "Preferences::setNoAutoStart: Autostart file is not read/write:" << autostartFileRW;
0234                 return;
0235             }
0236         }
0237     }
0238 
0239     // Read the existing file and remove any "Hidden=" and "OnlyShowIn=" entries
0240     bool update = false;
0241     QStringList lines;
0242     {
0243         QFile file(autostartFile);
0244         if (!file.open(QIODevice::ReadOnly))
0245         {
0246             qCWarning(KALARM_LOG) << "Preferences::setNoAutoStart: Error reading autostart file:" << autostartFile;
0247             return;
0248         }
0249         QTextStream stream(&file);
0250         stream.setAutoDetectUnicode(true);
0251         lines = stream.readAll().split(QLatin1Char('\n'));
0252         for (int i = 0; i < lines.size(); ++i)
0253         {
0254             const QString line = lines.at(i).trimmed();
0255             if (line.isEmpty())
0256             {
0257                 lines.removeAt(i);
0258                 --i;
0259             }
0260             else if (line.startsWith(QLatin1String("Hidden="))
0261                  ||  line.startsWith(QLatin1String("OnlyShowIn=")))
0262             {
0263                 lines.removeAt(i);
0264                 update = true;
0265                 --i;
0266             }
0267         }
0268     }
0269 
0270     if (yes)
0271     {
0272         // Add a "Hidden" entry to the local kalarm.autostart.desktop file, to
0273         // prevent autostart from happening.
0274         lines += QStringLiteral("Hidden=true");
0275         update = true;
0276     }
0277     if (update)
0278     {
0279         // Write the updated file
0280         QFileInfo info(configDirRW + QLatin1String("/autostart"));
0281         if (!info.exists())
0282         {
0283             // First, create the directory for it.
0284             if (!QDir(configDirRW).mkdir(QStringLiteral("autostart")))
0285             {
0286                 qCWarning(KALARM_LOG) << "Preferences::setNoAutoStart: Error creating autostart file directory:" << info.filePath();
0287                 return;
0288             }
0289         }
0290         QSaveFile file(autostartFileRW);
0291         if (!file.open(QIODevice::WriteOnly))
0292         {
0293             qCWarning(KALARM_LOG) << "Preferences::setNoAutoStart: Error writing autostart file:" << autostartFileRW;
0294             return;
0295         }
0296         QTextStream stream(&file);
0297         stream << lines.join(QLatin1Char('\n')) << "\n";
0298         // QSaveFile doesn't report a write error when the device is full (see Qt
0299         // bug 75077), so check that the data can actually be written by flush().
0300         if (!file.flush()  ||  !file.commit())   // save the file
0301         {
0302             qCWarning(KALARM_LOG) << "Preferences::setNoAutoStart: Error writing autostart file:" << autostartFileRW;
0303             return;
0304         }
0305         qCDebug(KALARM_LOG) << "Preferences::setNoAutoStart: Written" << autostartFileRW;
0306     }
0307 
0308     self()->setBase_NoAutoStart(yes);
0309 }
0310 
0311 /******************************************************************************
0312 * Get whether message windows should have a title bar and take keyboard focus.
0313 */
0314 bool Preferences::modalMessages()
0315 {
0316     return !KWindowSystem::isPlatformX11() || self()->base_ModalMessages();
0317 }
0318 
0319 /******************************************************************************
0320 * Set whether message windows should have a title bar and take keyboard focus.
0321 */
0322 void Preferences::setModalMessages(bool yes)
0323 {
0324     if (KWindowSystem::isPlatformX11())
0325         self()->setBase_ModalMessages(yes);
0326 }
0327 
0328 /******************************************************************************
0329 * Get the delay in seconds after a message window is displayed before its
0330 * buttons are activated.
0331 * Reply = 0 for no delay, but position windows as far from cursor as possible.
0332 */
0333 int Preferences::messageButtonDelay()
0334 {
0335     const int delay = self()->base_MessageButtonDelay();
0336     // On Wayland, window positions can't be set, so return a minimum delay of 1 second.
0337     return (delay <= 0  &&  KWindowSystem::isPlatformWayland()) ? 1 : delay;
0338 }
0339 
0340 /******************************************************************************
0341 * Get the user's time zone, or if none has been chosen, the system time zone.
0342 * Reply = time zone, or invalid to use the local time zone.
0343 */
0344 KADateTime::Spec Preferences::timeSpec()
0345 {
0346     const QByteArray zoneId = self()->mBase_TimeZone.toLatin1();
0347     return zoneId.isEmpty() ? KADateTime::LocalZone : KADateTime::Spec(QTimeZone(zoneId));
0348 }
0349 
0350 QTimeZone Preferences::timeSpecAsZone()
0351 {
0352     const QByteArray zoneId = self()->mBase_TimeZone.toLatin1();
0353     return zoneId.isEmpty() ? QTimeZone::systemTimeZone() : QTimeZone(zoneId);
0354 }
0355 
0356 void Preferences::setTimeSpec(const KADateTime::Spec& spec)
0357 {
0358     self()->setBase_TimeZone(spec.type() == KADateTime::TimeZone ? QString::fromLatin1(spec.timeZone().id()) : QString());
0359 }
0360 
0361 void Preferences::timeZoneChange(const QString& zone)
0362 {
0363     Q_UNUSED(zone);
0364     Q_EMIT mInstance->timeZoneChanged(timeSpec());
0365 }
0366 
0367 const Holidays& Preferences::holidays()
0368 {
0369     const QString regionCode = self()->mBase_HolidayRegion;
0370     if (!mHolidays)
0371         mHolidays = new Holidays(regionCode);
0372     else if (mHolidays->regionCode() != regionCode)
0373         mHolidays->setRegion(regionCode);
0374     return *mHolidays;
0375 }
0376 
0377 void Preferences::setHolidayRegion(const QString& regionCode)
0378 {
0379     self()->setBase_HolidayRegion(regionCode);
0380 }
0381 
0382 void Preferences::holidaysChange(const QString& regionCode)
0383 {
0384     Q_UNUSED(regionCode);
0385     Q_EMIT mInstance->holidaysChanged(holidays());
0386 }
0387 
0388 void Preferences::setStartOfDay(const QTime& t)
0389 {
0390     if (t != self()->mBase_StartOfDay.time())
0391     {
0392         self()->setBase_StartOfDay(QDateTime(QDate(1900,1,1), t));
0393         Q_EMIT mInstance->startOfDayChanged(t);
0394     }
0395 }
0396 
0397 // Called when the start of day value has changed in the config file
0398 void Preferences::startDayChange(const QDateTime& dt)
0399 {
0400     Q_EMIT mInstance->startOfDayChanged(dt.time());
0401 }
0402 
0403 QBitArray Preferences::workDays()
0404 {
0405     unsigned days = self()->base_WorkDays();
0406     QBitArray dayBits(7);
0407     for (int i = 0;  i < 7;  ++i)
0408         dayBits.setBit(i, days & (1 << i));
0409     return dayBits;
0410 }
0411 
0412 void Preferences::setWorkDays(const QBitArray& dayBits)
0413 {
0414     if (dayBits.size() != 7)
0415     {
0416         qCWarning(KALARM_LOG) << "Preferences::setWorkDays: Error! 'dayBits' parameter must have 7 elements: actual size" << dayBits.size();
0417         return;
0418     }
0419     unsigned days = 0;
0420     for (int i = 0;  i < 7;  ++i)
0421         if (dayBits.testBit(i))
0422             days |= 1 << i;
0423     self()->setBase_WorkDays(days);
0424 }
0425 
0426 void Preferences::workTimeChange(const QDateTime& start, const QDateTime& end, int days)
0427 {
0428     QBitArray dayBits(7);
0429     for (int i = 0;  i < 7;  ++i)
0430         if (days & (1 << i))
0431             dayBits.setBit(i);
0432     Q_EMIT mInstance->workTimeChanged(start.time(), end.time(), dayBits);
0433 }
0434 
0435 Preferences::MailClient Preferences::emailClient()
0436 {
0437     if (!useAkonadi())
0438         return sendmail;
0439     return static_cast<MailClient>(self()->mBase_EmailClient);
0440 }
0441 
0442 void Preferences::setEmailClient(MailClient client)
0443 {
0444     if (!useAkonadi())
0445         client = sendmail;
0446     self()->setBase_EmailClient(client);
0447 }
0448 
0449 bool Preferences::emailCopyToKMail()
0450 {
0451     if (!useAkonadi())
0452         return false;
0453     return self()->mBase_EmailCopyToKMail  &&  static_cast<MailClient>(self()->mBase_EmailClient) == sendmail;
0454 }
0455 
0456 void Preferences::setEmailCopyToKMail(bool yes)
0457 {
0458     if (!useAkonadi())
0459         yes = false;
0460     self()->setBase_EmailCopyToKMail(yes);
0461 }
0462 
0463 Preferences::MailFrom Preferences::emailFrom()
0464 {
0465     const QString from = self()->mBase_EmailFrom;
0466     if (from == FROM_KMAIL)
0467         return MAIL_FROM_KMAIL;
0468     if (from == FROM_SYS_SETTINGS)
0469         return MAIL_FROM_SYS_SETTINGS;
0470     return MAIL_FROM_ADDR;
0471 }
0472 
0473 /******************************************************************************
0474 * Get user's default 'From' email address.
0475 */
0476 QString Preferences::emailAddress()
0477 {
0478     const QString from = self()->mBase_EmailFrom;
0479     if (from == FROM_KMAIL)
0480         return Identities::identityManager()->defaultIdentity().fullEmailAddr();
0481     if (from == FROM_SYS_SETTINGS)
0482         return KAMail::controlCentreAddress();
0483     return from;
0484 }
0485 
0486 void Preferences::setEmailAddress(Preferences::MailFrom from, const QString& address)
0487 {
0488     QString out;
0489     switch (from)
0490     {
0491         case MAIL_FROM_KMAIL:        out = FROM_KMAIL; break;
0492         case MAIL_FROM_SYS_SETTINGS: out = FROM_SYS_SETTINGS; break;
0493         case MAIL_FROM_ADDR:         out = address; break;
0494         default:  return;
0495     }
0496     self()->setBase_EmailFrom(out);
0497 }
0498 
0499 Preferences::MailFrom Preferences::emailBccFrom()
0500 {
0501     const QString from = self()->mBase_EmailBccAddress;
0502     if (from == FROM_SYS_SETTINGS)
0503         return MAIL_FROM_SYS_SETTINGS;
0504     return MAIL_FROM_ADDR;
0505 }
0506 
0507 QString Preferences::emailBccAddress()
0508 {
0509     const QString from = self()->mBase_EmailBccAddress;
0510     if (from == FROM_SYS_SETTINGS)
0511         return KAMail::controlCentreAddress();
0512     return from;
0513 }
0514 
0515 bool Preferences::emailBccUseSystemSettings()
0516 {
0517     return self()->mBase_EmailBccAddress == FROM_SYS_SETTINGS;
0518 }
0519 
0520 void Preferences::setEmailBccAddress(bool useSystemSettings, const QString& address)
0521 {
0522     QString out;
0523     if (useSystemSettings)
0524         out = FROM_SYS_SETTINGS;
0525     else
0526         out = address;
0527     self()->setBase_EmailBccAddress(out);
0528 }
0529 
0530 QString Preferences::cmdXTermCommand()
0531 {
0532     QString cmd = translateXTermPath(self()->mBase_CmdXTermCommand, false);
0533     if (cmd.isEmpty())
0534     {
0535         // No terminal command is specified. If there is only one standard
0536         // terminal executable installed, set it as the default.
0537         const auto cmds = cmdXTermStandardCommands();
0538         if (cmds.size() == 1)
0539         {
0540             cmd = cmds.constBegin().value();
0541             self()->setBase_CmdXTermCommand(translateXTermPath(cmd, true));
0542             self()->save();
0543         }
0544     }
0545     return cmd;
0546 }
0547 
0548 std::pair<int, QString> Preferences::cmdXTermCommandIndex()
0549 {
0550     const QString xtermCmd = cmdXTermCommand();
0551     if (xtermCmd.isEmpty())
0552         return std::make_pair(-1, QString());
0553     int id = 0;
0554     for (const QString& cmd : xtermCommands)
0555     {
0556         ++id;
0557         if (xtermCmd == cmd)
0558             return std::make_pair(id, xtermCmd);   // index is 1 greater than the index into xtermCommands
0559     }
0560     return std::make_pair(0, xtermCmd);
0561 }
0562 
0563 void Preferences::setCmdXTermSpecialCommand(const QString& cmd)
0564 {
0565     self()->setBase_CmdXTermCommand(translateXTermPath(cmd, true));
0566 }
0567 
0568 void Preferences::setCmdXTermCommand(int index)
0569 {
0570     --index;   // convert to an index into xtermCommands
0571     if (index >= 0  &&  index < xtermCommands.size())
0572         setCmdXTermSpecialCommand(xtermCommands[index]);
0573 }
0574 
0575 QString Preferences::cmdXTermStandardCommand(int index)
0576 {
0577     --index;   // convert to an index into xtermCommands
0578     if (index >= 0  &&  index < xtermCommands.size())
0579     {
0580         splitXTermCommands();
0581         const QString exe = xtermCommandExes.at(index);
0582         if (!exe.isEmpty()  &&  !QStandardPaths::findExecutable(exe).isEmpty())
0583             return xtermCommands[index];
0584     }
0585     return {};
0586 }
0587 
0588 QHash<int, QString> Preferences::cmdXTermStandardCommands()
0589 {
0590     QHash<int, QString> result;
0591     splitXTermCommands();
0592     for (int i = 0, count = xtermCommands.count();  i < count;  ++i)
0593     {
0594         const QString exe = xtermCommandExes.at(i);
0595         if (!exe.isEmpty()  &&  !QStandardPaths::findExecutable(exe).isEmpty())
0596             result[i + 1] = xtermCommands[i];   // index is 1 greater than the index into xtermCommands
0597     }
0598     return result;
0599 }
0600 
0601 namespace
0602 {
0603 void splitXTermCommands()
0604 {
0605     if (xtermCommandExes.isEmpty())
0606     {
0607         for (const QString& cmd : xtermCommands)
0608         {
0609             const QStringList args = KShell::splitArgs(cmd);
0610             xtermCommandExes.append(args.isEmpty() ? QString() : args[0]);
0611         }
0612     }
0613 }
0614 }
0615 
0616 Preferences::SoundType Preferences::defaultSoundType()
0617 {
0618 #ifdef HAVE_TEXT_TO_SPEECH_SUPPORT
0619     return self()->base_DefaultSoundType();
0620 #else
0621     SoundType type = self()->base_DefaultSoundType();
0622     return (type == Sound_Speak) ? Sound_None : type;
0623 #endif
0624 }
0625 
0626 void Preferences::setDefaultSoundType(SoundType type)
0627 {
0628 #ifndef HAVE_TEXT_TO_SPEECH_SUPPORT
0629     if (type == Sound_Speak)
0630         return;
0631 #endif
0632     self()->setBase_DefaultSoundType(type);
0633 }
0634 
0635 void Preferences::connect(const char* signal, const QObject* receiver, const char* member)
0636 {
0637     QObject::connect(self(), signal, receiver, member);
0638 }
0639 
0640 /******************************************************************************
0641 * Called to allow or suppress output of the specified message dialog, where the
0642 * dialog has a checkbox to turn notification off.
0643 */
0644 void Preferences::setNotify(const QString& messageID, bool notify)
0645 {
0646     KAMessageBox::saveDontShowAgainContinue(messageID, !notify);
0647 }
0648 
0649 /******************************************************************************
0650 * Return whether the specified message dialog is output, where the dialog has
0651 * a checkbox to turn notification off.
0652 * Reply = false if message has been suppressed (by preferences or by selecting
0653 *               "don't ask again")
0654 *       = true in all other cases.
0655 */
0656 bool Preferences::notifying(const QString& messageID)
0657 {
0658     return KAMessageBox::shouldBeShownContinue(messageID);
0659 }
0660 
0661 /******************************************************************************
0662 * Translate an X terminal command path to/from config file format.
0663 * Note that only a home directory specification at the start of the path is
0664 * translated, so there's no need to worry about missing out some of the
0665 * executable's path due to quotes etc.
0666 * N.B. Calling KConfig::read/writePathEntry() on the entire command line
0667 *      causes a crash on some systems, so it's necessary to extract the
0668 *      executable path first before processing.
0669 */
0670 QString translateXTermPath(const QString& cmdline, bool write)
0671 {
0672     QString params = cmdline;
0673     QString cmd = ShellProcess::splitCommandLine(params);
0674 
0675     // Translate any home directory specification at the start of the
0676     // executable's path.
0677     KConfigGroup group(KSharedConfig::openConfig(), GENERAL_GROUP);
0678     if (write)
0679     {
0680         group.writePathEntry(TEMP, cmd);
0681         cmd = group.readEntry(TEMP, QString());
0682     }
0683     else
0684     {
0685         group.writeEntry(TEMP, cmd);
0686         cmd = group.readPathEntry(TEMP, QString());
0687     }
0688     group.deleteEntry(TEMP);
0689     return cmd + params;
0690 }
0691 
0692 #include "moc_preferences.cpp"
0693 
0694 // vim: et sw=4: