diff --git a/src/kexiutils/utils.cpp b/src/kexiutils/utils.cpp index 9db0e6e0d..5e0a3904b 100644 --- a/src/kexiutils/utils.cpp +++ b/src/kexiutils/utils.cpp @@ -1,1133 +1,1139 @@ /* This file is part of the KDE project Copyright (C) 2003-2017 Jarosław Staniek Contains code from kglobalsettings.cpp: Copyright (C) 2000, 2006 David Faure Copyright (C) 2008 Friedrich W. H. Kossebau Contains code from kdialog.cpp: Copyright (C) 1998 Thomas Tanghus (tanghus@earthling.net) Additions 1999-2000 by Espen Sand (espen@kde.org) and Holger Freyther 2005-2009 Olivier Goffart 2006 Tobias Koenig This program 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 program 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 program; see the file COPYING. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include "utils.h" #include "utils_p.h" #include "FontSettings_p.h" #include "kexiutils_global.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #if HAVE_LANGINFO_H #include #endif #ifdef Q_OS_WIN #include static QRgb qt_colorref2qrgb(COLORREF col) { return qRgb(GetRValue(col), GetGValue(col), GetBValue(col)); } #endif using namespace KexiUtils; DelayedCursorHandler::DelayedCursorHandler() : startedOrActive(false) { timer.setSingleShot(true); connect(&timer, SIGNAL(timeout()), this, SLOT(show())); } void DelayedCursorHandler::start(bool noDelay) { startedOrActive = true; timer.start(noDelay ? 0 : 1000); } void DelayedCursorHandler::stop() { startedOrActive = false; timer.stop(); QApplication::restoreOverrideCursor(); } void DelayedCursorHandler::show() { QApplication::restoreOverrideCursor(); QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); } Q_GLOBAL_STATIC(DelayedCursorHandler, _delayedCursorHandler) void KexiUtils::setWaitCursor(bool noDelay) { if (qobject_cast(qApp)) { _delayedCursorHandler->start(noDelay); } } void KexiUtils::removeWaitCursor() { if (qobject_cast(qApp)) { _delayedCursorHandler->stop(); } } WaitCursor::WaitCursor(bool noDelay) { setWaitCursor(noDelay); } WaitCursor::~WaitCursor() { removeWaitCursor(); } WaitCursorRemover::WaitCursorRemover() { m_reactivateCursor = _delayedCursorHandler->startedOrActive; _delayedCursorHandler->stop(); } WaitCursorRemover::~WaitCursorRemover() { if (m_reactivateCursor) _delayedCursorHandler->start(true); } //-------------------------------------------------------------------------------- QObject* KexiUtils::findFirstQObjectChild(QObject *o, const char* className, const char* objName) { if (!o) return 0; const QObjectList list(o->children()); foreach(QObject *child, list) { if (child->inherits(className) && (!objName || child->objectName() == objName)) return child; } //try children foreach(QObject *child, list) { child = findFirstQObjectChild(child, className, objName); if (child) return child; } return 0; } QMetaProperty KexiUtils::findPropertyWithSuperclasses(const QObject* object, const char* name) { const int index = object->metaObject()->indexOfProperty(name); if (index == -1) return QMetaProperty(); return object->metaObject()->property(index); } bool KexiUtils::objectIsA(QObject* object, const QList& classNames) { foreach(const QByteArray& ba, classNames) { if (objectIsA(object, ba.constData())) return true; } return false; } QList KexiUtils::methodsForMetaObject( const QMetaObject *metaObject, QFlags types, QFlags access) { const int count = metaObject ? metaObject->methodCount() : 0; QList result; for (int i = 0; i < count; i++) { QMetaMethod method(metaObject->method(i)); if (types & method.methodType() && access & method.access()) result += method; } return result; } QList KexiUtils::methodsForMetaObjectWithParents( const QMetaObject *metaObject, QFlags types, QFlags access) { QList result; while (metaObject) { const int count = metaObject->methodCount(); for (int i = 0; i < count; i++) { QMetaMethod method(metaObject->method(i)); if (types & method.methodType() && access & method.access()) result += method; } metaObject = metaObject->superClass(); } return result; } QList KexiUtils::propertiesForMetaObject( const QMetaObject *metaObject) { const int count = metaObject ? metaObject->propertyCount() : 0; QList result; for (int i = 0; i < count; i++) result += metaObject->property(i); return result; } QList KexiUtils::propertiesForMetaObjectWithInherited( const QMetaObject *metaObject) { QList result; while (metaObject) { const int count = metaObject->propertyCount(); for (int i = 0; i < count; i++) result += metaObject->property(i); metaObject = metaObject->superClass(); } return result; } QStringList KexiUtils::enumKeysForProperty(const QMetaProperty& metaProperty) { QStringList result; QMetaEnum enumerator(metaProperty.enumerator()); const int count = enumerator.keyCount(); for (int i = 0; i < count; i++) result.append(QString::fromLatin1(enumerator.key(i))); return result; } QString KexiUtils::fileDialogFilterString(const QMimeType &mime, bool kdeFormat) { if (!mime.isValid()) { return QString(); } QString str; if (kdeFormat) { if (mime.globPatterns().isEmpty()) { str = "*"; } else { str = mime.globPatterns().join(" "); } str += "|"; } str += mime.comment(); if (!mime.globPatterns().isEmpty() || !kdeFormat) { str += " ("; if (mime.globPatterns().isEmpty()) str += "*"; else str += mime.globPatterns().join("; "); str += ")"; } if (kdeFormat) str += "\n"; else str += ";;"; return str; } QString KexiUtils::fileDialogFilterString(const QString& mimeName, bool kdeFormat) { QMimeDatabase db; QMimeType mime = db.mimeTypeForName(mimeName); return fileDialogFilterString(mime, kdeFormat); } QString KexiUtils::fileDialogFilterStrings(const QStringList& mimeStrings, bool kdeFormat) { QString ret; QStringList::ConstIterator endIt = mimeStrings.constEnd(); for (QStringList::ConstIterator it = mimeStrings.constBegin(); it != endIt; ++it) ret += fileDialogFilterString(*it, kdeFormat); return ret; } //! @internal static QFileDialog* getImageDialog(QWidget *parent, const QString &caption, const QUrl &directory, const QList &supportedMimeTypes) { QFileDialog *dialog = new QFileDialog(parent, caption); dialog->setDirectoryUrl(directory); const QStringList mimeTypeFilters = KexiUtils::convertTypesUsingFunction(supportedMimeTypes); dialog->setMimeTypeFilters(mimeTypeFilters); return dialog; } QUrl KexiUtils::getOpenImageUrl(QWidget *parent, const QString &caption, const QUrl &directory) { QScopedPointer dialog( getImageDialog(parent, caption.isEmpty() ? i18n("Open") : caption, directory, QImageReader::supportedMimeTypes())); dialog->setFileMode(QFileDialog::ExistingFile); dialog->setAcceptMode(QFileDialog::AcceptOpen); - dialog->exec(); - return dialog->selectedUrls().value(0); + if (QDialog::Accepted == dialog->exec()) { + return dialog->selectedUrls().value(0); + } else { + return QUrl(); + } } QUrl KexiUtils::getSaveImageUrl(QWidget *parent, const QString &caption, const QUrl &directory) { QScopedPointer dialog( getImageDialog(parent, caption.isEmpty() ? i18n("Save") : caption, directory, QImageWriter::supportedMimeTypes())); dialog->setAcceptMode(QFileDialog::AcceptSave); - dialog->exec(); - return dialog->selectedUrls().value(0); + if (QDialog::Accepted == dialog->exec()) { + return dialog->selectedUrls().value(0); + } else { + return QUrl(); + } } QColor KexiUtils::blendedColors(const QColor& c1, const QColor& c2, int factor1, int factor2) { return QColor( int((c1.red()*factor1 + c2.red()*factor2) / (factor1 + factor2)), int((c1.green()*factor1 + c2.green()*factor2) / (factor1 + factor2)), int((c1.blue()*factor1 + c2.blue()*factor2) / (factor1 + factor2))); } QColor KexiUtils::contrastColor(const QColor& c) { int g = qGray(c.rgb()); if (g > 110) return c.dark(200); else if (g > 80) return c.light(150); else if (g > 20) return c.light(300); return Qt::gray; } QColor KexiUtils::bleachedColor(const QColor& c, int factor) { int h, s, v; c.getHsv(&h, &s, &v); QColor c2; if (factor < 100) factor = 100; if (s >= 250 && v >= 250) //for colors like cyan or red, make the result more white s = qMax(0, s - factor - 50); else if (s <= 5 && v <= 5) v += factor - 50; c2.setHsv(h, s, qMin(255, v + factor - 100)); return c2; } QIcon KexiUtils::colorizeIconToTextColor(const QPixmap& icon, const QPalette& palette, QPalette::ColorRole role) { QPixmap pm( KIconEffect().apply(icon, KIconEffect::Colorize, 1.0f, palette.color(role), false)); KIconEffect::semiTransparent(pm); return QIcon(pm); } QPixmap KexiUtils::emptyIcon(KIconLoader::Group iconGroup) { QPixmap noIcon(IconSize(iconGroup), IconSize(iconGroup)); noIcon.fill(Qt::transparent); return noIcon; } static void drawOrScalePixmapInternal(QPainter* p, const QMargins& margins, const QRect& rect, QPixmap* pixmap, QPoint* pos, Qt::Alignment alignment, bool scaledContents, bool keepAspectRatio, Qt::TransformationMode transformMode = Qt::FastTransformation) { Q_ASSERT(pos); if (pixmap->isNull()) return; const bool fast = false; const int w = rect.width() - margins.left() - margins.right(); const int h = rect.height() - margins.top() - margins.bottom(); //! @todo we can optimize painting by drawing rescaled pixmap here //! and performing detailed painting later (using QTimer) // QPixmap pixmapBuffer; // QPainter p2; // QPainter *target; // if (fast) { // target = p; // } else { // target = &p2; // } //! @todo only create buffered pixmap of the minimum size and then do not fillRect() // target->fillRect(0,0,rect.width(),rect.height(), backgroundColor); *pos = rect.topLeft() + QPoint(margins.left(), margins.top()); if (scaledContents) { if (keepAspectRatio) { QImage img(pixmap->toImage()); img = img.scaled(w, h, Qt::KeepAspectRatio, transformMode); if (img.width() < w) { if (alignment & Qt::AlignRight) pos->setX(pos->x() + w - img.width()); else if (alignment & Qt::AlignHCenter) pos->setX(pos->x() + w / 2 - img.width() / 2); } else if (img.height() < h) { if (alignment & Qt::AlignBottom) pos->setY(pos->y() + h - img.height()); else if (alignment & Qt::AlignVCenter) pos->setY(pos->y() + h / 2 - img.height() / 2); } if (p) { p->drawImage(*pos, img); } else { *pixmap = QPixmap::fromImage(img); } } else { if (!fast) { *pixmap = pixmap->scaled(w, h, Qt::IgnoreAspectRatio, transformMode); if (p) { p->drawPixmap(*pos, *pixmap); } } } } else { if (alignment & Qt::AlignRight) pos->setX(pos->x() + w - pixmap->width()); else if (alignment & Qt::AlignHCenter) pos->setX(pos->x() + w / 2 - pixmap->width() / 2); else //left, etc. pos->setX(pos->x()); if (alignment & Qt::AlignBottom) pos->setY(pos->y() + h - pixmap->height()); else if (alignment & Qt::AlignVCenter) pos->setY(pos->y() + h / 2 - pixmap->height() / 2); else //top, etc. pos->setY(pos->y()); *pos += QPoint(margins.left(), margins.top()); if (p) { p->drawPixmap(*pos, *pixmap); } } } void KexiUtils::drawPixmap(QPainter* p, const QMargins& margins, const QRect& rect, const QPixmap& pixmap, Qt::Alignment alignment, bool scaledContents, bool keepAspectRatio, Qt::TransformationMode transformMode) { QPixmap px(pixmap); QPoint pos; drawOrScalePixmapInternal(p, margins, rect, &px, &pos, alignment, scaledContents, keepAspectRatio, transformMode); } QPixmap KexiUtils::scaledPixmap(const QMargins& margins, const QRect& rect, const QPixmap& pixmap, QPoint* pos, Qt::Alignment alignment, bool scaledContents, bool keepAspectRatio, Qt::TransformationMode transformMode) { QPixmap px(pixmap); drawOrScalePixmapInternal(0, margins, rect, &px, pos, alignment, scaledContents, keepAspectRatio, transformMode); return px; } bool KexiUtils::loadPixmapFromData(QPixmap *pixmap, const QByteArray &data, const char *format) { bool ok = pixmap->loadFromData(data, format); if (ok) { return true; } if (format) { return false; } const QList commonFormats({"png", "jpg", "bmp", "tif"}); QList formats(commonFormats); for(int i=0; ;) { ok = pixmap->loadFromData(data, formats[i]); if (ok) { return true; } ++i; if (i == formats.count()) {// try harder if (i == commonFormats.count()) { formats += QImageReader::supportedImageFormats(); if (formats.count() == commonFormats.count()) { break; // sanity check } } else { break; } } } return false; } void KexiUtils::setFocusWithReason(QWidget* widget, Qt::FocusReason reason) { if (!widget) return; QFocusEvent fe(QEvent::FocusIn, reason); QCoreApplication::sendEvent(widget, &fe); } void KexiUtils::unsetFocusWithReason(QWidget* widget, Qt::FocusReason reason) { if (!widget) return; QFocusEvent fe(QEvent::FocusOut, reason); QCoreApplication::sendEvent(widget, &fe); } //-------- void KexiUtils::adjustIfRtl(QMargins *margins) { if (margins && QGuiApplication::isRightToLeft()) { const int left = margins->left(); margins->setLeft(margins->right()); margins->setRight(left); } } //--------- Q_GLOBAL_STATIC(FontSettingsData, g_fontSettings) QFont KexiUtils::smallestReadableFont() { return g_fontSettings->font(FontSettingsData::SmallestReadableFont); } //--------------------- KTextEditorFrame::KTextEditorFrame(QWidget * parent, Qt::WindowFlags f) : QFrame(parent, f) { QEvent dummy(QEvent::StyleChange); changeEvent(&dummy); } void KTextEditorFrame::changeEvent(QEvent *event) { if (event->type() == QEvent::StyleChange) { if (style()->objectName() != "oxygen") // oxygen already nicely paints the frame setFrameStyle(QFrame::Sunken | QFrame::StyledPanel); else setFrameStyle(QFrame::NoFrame); } } //--------------------- int KexiUtils::marginHint() { return QApplication::style()->pixelMetric(QStyle::PM_DefaultChildMargin); } int KexiUtils::spacingHint() { return QApplication::style()->pixelMetric(QStyle::PM_DefaultLayoutSpacing); } void KexiUtils::setStandardMarginsAndSpacing(QLayout *layout) { setMargins(layout, KexiUtils::marginHint()); layout->setSpacing(KexiUtils::spacingHint()); } void KexiUtils::setMargins(QLayout *layout, int value) { layout->setContentsMargins(value, value, value, value); } void KexiUtils::replaceColors(QPixmap* original, const QColor& color) { Q_ASSERT(original); QImage dest(original->toImage()); replaceColors(&dest, color); *original = QPixmap::fromImage(dest); } void KexiUtils::replaceColors(QImage* original, const QColor& color) { Q_ASSERT(original); *original = original->convertToFormat(QImage::Format_ARGB32_Premultiplied); QPainter p(original); p.setCompositionMode(QPainter::CompositionMode_SourceIn); p.fillRect(original->rect(), color); } bool KexiUtils::isLightColorScheme() { return KColorScheme(QPalette::Active, KColorScheme::Window).background().color().lightness() >= 128; } int KexiUtils::dimmedAlpha() { return 150; } QPalette KexiUtils::paletteWithDimmedColor(const QPalette &pal, QPalette::ColorGroup group, QPalette::ColorRole role) { QPalette result(pal); QColor color(result.color(group, role)); color.setAlpha(dimmedAlpha()); result.setColor(group, role, color); return result; } QPalette KexiUtils::paletteWithDimmedColor(const QPalette &pal, QPalette::ColorRole role) { QPalette result(pal); QColor color(result.color(role)); color.setAlpha(dimmedAlpha()); result.setColor(role, color); return result; } QPalette KexiUtils::paletteForReadOnly(const QPalette &palette) { QPalette p(palette); p.setBrush(QPalette::Base, palette.brush(QPalette::Disabled, QPalette::Base)); p.setBrush(QPalette::Text, palette.brush(QPalette::Disabled, QPalette::Text)); p.setBrush(QPalette::Highlight, palette.brush(QPalette::Disabled, QPalette::Highlight)); p.setBrush(QPalette::HighlightedText, palette.brush(QPalette::Disabled, QPalette::HighlightedText)); return p; } void KexiUtils::setBackgroundColor(QWidget *widget, const QColor &color) { widget->setAutoFillBackground(true); QPalette pal(widget->palette()); pal.setColor(widget->backgroundRole(), color); widget->setPalette(pal); } //--------------------- void KexiUtils::installRecursiveEventFilter(QObject *object, QObject *filter) { if (!object || !filter || !object->isWidgetType()) return; // qDebug() << "Installing event filter on widget:" << object // << "directed to" << filter->objectName(); object->installEventFilter(filter); const QObjectList list(object->children()); foreach(QObject *obj, list) { installRecursiveEventFilter(obj, filter); } } void KexiUtils::removeRecursiveEventFilter(QObject *object, QObject *filter) { object->removeEventFilter(filter); if (!object->isWidgetType()) return; const QObjectList list(object->children()); foreach(QObject *obj, list) { removeRecursiveEventFilter(obj, filter); } } PaintBlocker::PaintBlocker(QWidget* parent) : QObject(parent) , m_enabled(true) { parent->installEventFilter(this); } void PaintBlocker::setEnabled(bool set) { m_enabled = set; } bool PaintBlocker::enabled() const { return m_enabled; } bool PaintBlocker::eventFilter(QObject* watched, QEvent* event) { if (m_enabled && watched == parent() && event->type() == QEvent::Paint) { return true; } return false; } tristate KexiUtils::openHyperLink(const QUrl &url, QWidget *parent, const OpenHyperlinkOptions &options) { if (url.isLocalFile()) { QFileInfo fileInfo(url.toLocalFile()); if (!fileInfo.exists()) { KMessageBox::sorry(parent, xi18nc("@info", "The file or directory %1 does not exist.", fileInfo.absoluteFilePath())); return false; } } if (!url.isValid()) { KMessageBox::sorry(parent, xi18nc("@info", "Invalid hyperlink %1.", url.url(QUrl::PreferLocalFile))); return false; } QMimeDatabase db; QString type = db.mimeTypeForUrl(url).name(); if (!options.allowExecutable && KRun::isExecutableFile(url, type)) { KMessageBox::sorry(parent, xi18nc("@info", "Executable %1 not allowed.", url.url(QUrl::PreferLocalFile))); return false; } if (!options.allowRemote && !url.isLocalFile()) { KMessageBox::sorry(parent, xi18nc("@info", "Remote hyperlink %1 not allowed.", url.url(QUrl::PreferLocalFile))); return false; } if (KRun::isExecutableFile(url, type)) { int ret = KMessageBox::questionYesNo(parent , xi18nc("@info", "Do you want to run this file?" "Running executables can be dangerous.") , QString() , KGuiItem(xi18nc("@action:button Run script file", "Run"), koIconName("system-run")) , KStandardGuiItem::no() , "AllowRunExecutable", KMessageBox::Dangerous); if (ret != KMessageBox::Yes) { return cancelled; } } switch(options.tool) { case OpenHyperlinkOptions::DefaultHyperlinkTool: #if KIO_VERSION >= QT_VERSION_CHECK(5, 31, 0) return KRun::runUrl(url, type, parent, KRun::RunExecutables); #else return KRun::runUrl(url, type, parent); #endif case OpenHyperlinkOptions::BrowserHyperlinkTool: return QDesktopServices::openUrl(url); case OpenHyperlinkOptions::MailerHyperlinkTool: return QDesktopServices::openUrl(url); default:; } return false; } // ---- KexiDBDebugTreeWidget::KexiDBDebugTreeWidget(QWidget *parent) : QTreeWidget(parent) { } void KexiDBDebugTreeWidget::copy() { if (currentItem()) { qApp->clipboard()->setText(currentItem()->text(0)); } } // ---- DebugWindow::DebugWindow(QWidget * parent) : QWidget(parent, Qt::Window) { } // ---- QSize KexiUtils::comboBoxArrowSize(QStyle *style) { if (!style) { style = QApplication::style(); } QStyleOptionComboBox cbOption; return style->subControlRect(QStyle::CC_ComboBox, &cbOption, QStyle::SC_ComboBoxArrow).size(); } void KexiUtils::addDirtyFlag(QString *text) { Q_ASSERT(text); *text = xi18nc("'Dirty (modified) object' flag", "%1*", *text); } //! From klocale_kde.cpp //! @todo KEXI3 support other OS-es (use from klocale_*.cpp) static QByteArray systemCodeset() { QByteArray codeset; #if HAVE_LANGINFO_H // Qt since 4.2 always returns 'System' as codecForLocale and KDE (for example // KEncodingFileDialog) expects real encoding name. So on systems that have langinfo.h use // nl_langinfo instead, just like Qt compiled without iconv does. Windows already has its own // workaround codeset = nl_langinfo(CODESET); if ((codeset == "ANSI_X3.4-1968") || (codeset == "US-ASCII")) { // means ascii, "C"; QTextCodec doesn't know, so avoid warning codeset = "ISO-8859-1"; } #endif return codeset; } QTextCodec* g_codecForEncoding = 0; bool setEncoding(int mibEnum) { QTextCodec *codec = QTextCodec::codecForMib(mibEnum); if (codec) { g_codecForEncoding = codec; } return codec != 0; } //! From klocale_kde.cpp static void initEncoding() { if (!g_codecForEncoding) { // This all made more sense when we still had the EncodingEnum config key. QByteArray codeset = systemCodeset(); if (!codeset.isEmpty()) { QTextCodec *codec = QTextCodec::codecForName(codeset); if (codec) { setEncoding(codec->mibEnum()); } } else { setEncoding(QTextCodec::codecForLocale()->mibEnum()); } if (!g_codecForEncoding) { qWarning() << "Cannot resolve system encoding, defaulting to ISO 8859-1."; const int mibDefault = 4; // ISO 8859-1 setEncoding(mibDefault); } Q_ASSERT(g_codecForEncoding); } } QByteArray KexiUtils::encoding() { initEncoding(); return g_codecForEncoding->name(); } namespace { //! @internal for graphicEffectsLevel() class GraphicEffectsLevel { public: GraphicEffectsLevel() { KConfigGroup g(KSharedConfig::openConfig(), "KDE-Global GUI Settings"); // Asking for hasKey we do not ask for graphicEffectsLevelDefault() that can // contain some very slow code. If we can save that time, do it. (ereslibre) if (g.hasKey("GraphicEffectsLevel")) { value = ((GraphicEffects) g.readEntry("GraphicEffectsLevel", QVariant((int) NoEffects)).toInt()); return; } // For now, let always enable animations by default. The plan is to make // this code a bit smarter. (ereslibre) value = ComplexAnimationEffects; } GraphicEffects value; }; } Q_GLOBAL_STATIC(GraphicEffectsLevel, g_graphicEffectsLevel) GraphicEffects KexiUtils::graphicEffectsLevel() { return g_graphicEffectsLevel->value; } #if defined Q_OS_UNIX && !defined Q_OS_MACOS //! For detectedDesktopSession() class DetectedDesktopSession { public: DetectedDesktopSession() : name(detect()) {} const QByteArray name; private: static QByteArray detect() { // https://www.freedesktop.org/software/systemd/man/pam_systemd.html#%24XDG_SESSION_DESKTOP // KDE, GNOME, UNITY, LXDE, MATE, XFCE... const QString xdgSessionDesktop = qgetenv("XDG_SESSION_DESKTOP").trimmed(); if (!xdgSessionDesktop.isEmpty()) { return xdgSessionDesktop.toLatin1().toUpper(); } // Similar to detectDesktopEnvironment() from qgenericunixservices.cpp const QString xdgCurrentDesktop = qgetenv("XDG_CURRENT_DESKTOP").trimmed(); if (!xdgCurrentDesktop.isEmpty()) { return xdgCurrentDesktop.toLatin1().toUpper(); } // fallbacks if (!qEnvironmentVariableIsEmpty("KDE_FULL_SESSION")) { return QByteArrayLiteral("KDE"); } if (!qEnvironmentVariableIsEmpty("GNOME_DESKTOP_SESSION_ID")) { return QByteArrayLiteral("GNOME"); } const QString desktopSession = qgetenv("DESKTOP_SESSION").trimmed(); if (desktopSession.compare("gnome", Qt::CaseInsensitive) == 0) { return QByteArrayLiteral("GNOME"); } else if (desktopSession.compare("xfce", Qt::CaseInsensitive) == 0) { return QByteArrayLiteral("XFCE"); } return QByteArray(); } }; Q_GLOBAL_STATIC(DetectedDesktopSession, s_detectedDesktopSession) QByteArray KexiUtils::detectedDesktopSession() { return s_detectedDesktopSession->name; } //! @return value of XFCE property @a property for channel @a channel //! Sets the value pointed by @a ok to status. //! @todo Should be part of desktop integration or KF static QByteArray xfceSettingValue(const QByteArray &channel, const QByteArray &property, bool *ok = nullptr) { if (ok) { *ok = false; } QByteArray result; const QString command = QString::fromLatin1("xfconf-query -c \"%1\" -p \"%2\"") .arg(channel.constData()) .arg(property.constData()); QProcess process; process.start(command, QIODevice::ReadOnly | QIODevice::Text); if (!process.waitForStarted()) { qWarning() << "Count not execute command" << command << "error:" << process.error(); return QByteArray(); } if (!process.waitForFinished() || process.exitStatus() != QProcess::NormalExit) { qWarning() << "Count not finish command" << command << "error:" << process.error() << "exit status:" << process.exitStatus(); return QByteArray(); } if (ok) { *ok = true; } if (process.exitCode() == 0) { result = process.readAll(); result.chop(1); } return result; // !=0 e.g. for "no such property or channel" } #else QByteArray KexiUtils::detectedDesktopSession() { return QByteArray(); } #endif bool KexiUtils::activateItemsOnSingleClick(QWidget *widget) { const KConfigGroup mainWindowGroup = KSharedConfig::openConfig()->group("MainWindow"); #ifdef Q_OS_WIN return mainWindowGroup.readEntry("SingleClickOpensItem", true); #else if (mainWindowGroup.hasKey("SingleClickOpensItem")) { return mainWindowGroup.readEntry("SingleClickOpensItem", true); } const QByteArray desktopSession = detectedDesktopSession(); if (desktopSession == "XFCE") { /* To test: Set to true: fconf-query -c xfce4-desktop -p /desktop-icons/single-click -n -t bool -s true Get value: xfconf-query -c xfce4-desktop -p /desktop-icons/single-click Reset: xfconf-query -c xfce4-desktop -p /desktop-icons/single-click -r */ return xfceSettingValue("xfce4-desktop", "/desktop-icons/single-click") == "true"; } # if QT_VERSION >= QT_VERSION_CHECK(5, 5, 0) Q_UNUSED(widget) return QApplication::styleHints()->singleClickActivation(); # else QStyle *style = widget ? widget->style() : QApplication::style(); return style->styleHint(QStyle::SH_ItemView_ActivateItemOnSingleClick, 0, widget); # endif #endif } // NOTE: keep this in sync with kdebase/workspace/kcontrol/colors/colorscm.cpp QColor KexiUtils::inactiveTitleColor() { #ifdef Q_OS_WIN return qt_colorref2qrgb(GetSysColor(COLOR_INACTIVECAPTION)); #else KConfigGroup g(KSharedConfig::openConfig(), "WM"); return g.readEntry("inactiveBackground", QColor(224, 223, 222)); #endif } // NOTE: keep this in sync with kdebase/workspace/kcontrol/colors/colorscm.cpp QColor KexiUtils::inactiveTextColor() { #ifdef Q_OS_WIN return qt_colorref2qrgb(GetSysColor(COLOR_INACTIVECAPTIONTEXT)); #else KConfigGroup g(KSharedConfig::openConfig(), "WM"); return g.readEntry("inactiveForeground", QColor(75, 71, 67)); #endif } // NOTE: keep this in sync with kdebase/workspace/kcontrol/colors/colorscm.cpp QColor KexiUtils::activeTitleColor() { #ifdef Q_OS_WIN return qt_colorref2qrgb(GetSysColor(COLOR_ACTIVECAPTION)); #else KConfigGroup g(KSharedConfig::openConfig(), "WM"); return g.readEntry("activeBackground", QColor(48, 174, 232)); #endif } // NOTE: keep this in sync with kdebase/workspace/kcontrol/colors/colorscm.cpp QColor KexiUtils::activeTextColor() { #ifdef Q_OS_WIN return qt_colorref2qrgb(GetSysColor(COLOR_CAPTIONTEXT)); #else KConfigGroup g(KSharedConfig::openConfig(), "WM"); return g.readEntry("activeForeground", QColor(255, 255, 255)); #endif } QString KexiUtils::makeStandardCaption(const QString &userCaption, CaptionFlags flags) { QString caption = KAboutData::applicationData().displayName(); if (caption.isEmpty()) { return QCoreApplication::instance()->applicationName(); } QString captionString = userCaption.isEmpty() ? caption : userCaption; // If the document is modified, add '[modified]'. if (flags & ModifiedCaption) { captionString += QString::fromUtf8(" [") + xi18n("modified") + QString::fromUtf8("]"); } if (!userCaption.isEmpty()) { // Add the application name if: // User asked for it, it's not a duplication and the app name (caption()) is not empty if (flags & AppNameCaption && !caption.isEmpty() && !userCaption.endsWith(caption)) { // TODO: check to see if this is a transient/secondary window before trying to add the app name // on platforms that need this captionString += xi18nc("Document/application separator in titlebar", " – ") + caption; } } return captionString; } QString themedIconName(const QString &name) { static bool firstUse = true; if (firstUse) { // workaround for some kde-related crash const bool _unused = KIconLoader::global()->iconPath(name, KIconLoader::NoGroup, true).isEmpty(); Q_UNUSED(_unused); firstUse = false; } // try load themed icon const QColor background = qApp->palette().background().color(); const bool useDarkIcons = background.value() > 100; return QLatin1String(useDarkIcons ? "dark_" : "light_") + name; } QIcon themedIcon(const QString &name) { const QString realName(themedIconName(name)); const QIcon icon = QIcon::fromTheme(realName); // fallback if (icon.isNull()) { return QIcon::fromTheme(name); } return icon; } QString KexiUtils::localizedStringToHtmlSubstring(const KLocalizedString& string) { return string.toString(Kuit::RichText) .remove(QLatin1String("")).remove(QLatin1String("")); } bool KexiUtils::cursorAtEnd(const QLineEdit *lineEdit) { if (!lineEdit) { return false; } if (lineEdit->inputMask().isEmpty()) { return lineEdit->cursorPosition() >= lineEdit->displayText().length(); } else { return lineEdit->cursorPosition() >= (lineEdit->displayText().length() - 1); } }