diff --git a/src/config-kexi.h.cmake b/src/config-kexi.h.cmake index 9367860bb..82f24ac66 100644 --- a/src/config-kexi.h.cmake +++ b/src/config-kexi.h.cmake @@ -1,140 +1,142 @@ /* This file is part of the KDE project - Copyright (C) 2006-2016 Jarosław Staniek + Copyright (C) 2006-2018 Jarosław Staniek 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. */ #ifndef KEXI_CONFIG_H #define KEXI_CONFIG_H /* config-kexi.h. Generated by cmake from config-kexi.h.cmake */ /*! @file config-kexi.h Global Kexi configuration (build time) */ #include //! @def KEXI_DESKTOP //! @brief If defined, a desktop version of Kexi is compiled #cmakedefine KEXI_DESKTOP //! @def KEXI_MOBILE //! @brief If defined, a mobile version of Kexi is compiled #cmakedefine KEXI_MOBILE /* define if you have libreadline available */ /* TODO: detect #define HAVE_READLINE 1 */ //! @def HAVE_UNAME //! @brief If defined, uname(2) is available #cmakedefine HAVE_UNAME 1 /*! For KexiUtils::encoding() */ #cmakedefine01 HAVE_LANGINFO_H //! @def HAVE_KCRASH //! @brief if defined, KCrash is available #cmakedefine HAVE_KCRASH //! @def HAVE_MARBLE //! @brief if defined, Marble widget library is available #cmakedefine HAVE_MARBLE //! @def HAVE_QTWEBKITWIDGETS //! @brief if defined, QtWebKit widgets library is available #cmakedefine HAVE_QTWEBKITWIDGETS //! @def COMPILING_TESTS //! @brief if defined, tests are enabled #cmakedefine COMPILING_TESTS //! @def COMPILING_EXAMPLES //! @brief if defined, examples are enabled and installed #cmakedefine COMPILING_EXAMPLES //! @def KEXI_DEBUG_GUI //! @brief If defined, a debugging GUI for Kexi is enabled #cmakedefine KEXI_DEBUG_GUI #if defined KEXI_DEBUG_GUI && !defined KDB_DEBUG_GUI # error KEXI_DEBUG_GUI requires a KDB_DEBUG_GUI cmake option to be set too in KDb. #endif //! @def KEXI_MIGRATEMANAGER_DEBUG //! @brief Defined if debugging for the migrate driver manager is enabled #cmakedefine KEXI_MIGRATEMANAGER_DEBUG /* -- Experimental -- */ //! @def KEXI_SCRIPTS_SUPPORT //! @brief If defined, scripting GUI plugin is enabled in Kexi #cmakedefine KEXI_SCRIPTS_SUPPORT //! @def KEXI_MACROS_SUPPORT //! @brief If defined, macro GUI plugin is enabled in Kexi #cmakedefine KEXI_MACROS_SUPPORT //! @def KEXI_SHOW_UNFINISHED //! @brief If defined unfinished features are enabled and presented in Kexi. //! This is useful for testing but may confuse end-users. #cmakedefine KEXI_SHOW_UNFINISHED //! @def KEXI_SHOW_UNIMPLEMENTED //! @brief If defined show menu entries and dialogs just to give impression about development plans for Kexi //! Only recommended for test/development versions. #cmakedefine KEXI_SHOW_UNIMPLEMENTED //! @def KEXI_PROJECT_TEMPLATES //! @brief If defined, support for project templates is enabled in Kexi #cmakedefine KEXI_PROJECT_TEMPLATES +#ifndef KEXI_MOBILE //! @def KEXI_AUTORISE_TABBED_TOOLBAR //! @brief If defined, tabs in the main tabbed toolbar autorise in Kexi #cmakedefine KEXI_AUTORISE_TABBED_TOOLBAR //! @def KEXI_USE_KFILEWIDGET //! @brief If defined, KFileWidget-based inline file browser is used in Kexi. Otherwise a simple //! replacement file widget with native file dialogs is used. ON by default on UNIX, OFF by default //! on Windows and macOS. //! @note Non-plasma Linux desktops still default to the simple replacement at runtime. #cmakedefine KEXI_USE_KFILEWIDGET +#endif // !KEXI_MOBILE //! @def KEXI_FORM_CURSOR_PROPERTY_SUPPORT //! @brief If defined, "cursor" property is displayed in the form designer #cmakedefine KEXI_FORM_CURSOR_PROPERTY_SUPPORT //! @def KEXI_SHOW_CONTEXT_HELP //! @brief If defined, context help is displayed in Kexi main window #cmakedefine KEXI_SHOW_CONTEXT_HELP //! @def KEXI_QUICK_PRINTING_SUPPORT //! @brief If defined, print/print preview/print setup for tables/queries is enabled in the project navigator #cmakedefine KEXI_QUICK_PRINTING_SUPPORT //! @def KEXI_AUTOFIELD_FORM_WIDGET_SUPPORT //! @brief If defined, "auto field" form widget is available in the form designer #cmakedefine KEXI_AUTOFIELD_FORM_WIDGET_SUPPORT //! @def KEXI_LIST_FORM_WIDGET_SUPPORT //! @brief If defined, "list" form widget is available in the form designer #cmakedefine KEXI_LIST_FORM_WIDGET_SUPPORT //! @def KEXI_PIXMAP_COLLECTIONS_SUPPORT //! @brief If defined, support for pixmap collections is enabled #cmakedefine KEXI_PIXMAP_COLLECTIONS_SUPPORT #endif diff --git a/src/kexiutils/CMakeLists.txt b/src/kexiutils/CMakeLists.txt index fd0fdcc5f..ab7696321 100644 --- a/src/kexiutils/CMakeLists.txt +++ b/src/kexiutils/CMakeLists.txt @@ -1,97 +1,97 @@ add_definitions(-DKDE_DEFAULT_DEBUG_AREA=44024) include_directories(completer) set(kexiutils_LIB_SRCS utils.cpp FontSettings_p.cpp InternalPropertyMap.cpp SmallToolButton.cpp KexiCommandLinkButton.cpp FlowLayout.cpp transliteration_table.cpp kmessagewidget.cpp KexiContextMessage.cpp KexiTitleLabel.cpp KexiLinkWidget.cpp KexiLinkButton.cpp KexiCloseButton.cpp KexiAssistantPage.cpp KexiAssistantWidget.cpp KexiAnimatedLayout.cpp KexiCategorizedView.cpp KexiTester.cpp KexiJsonTrader.cpp KexiPushButton.cpp KexiFadeWidgetEffect.cpp KexiPluginMetaData.cpp completer/KexiCompleter.cpp ) if(SHOULD_BUILD_KEXI_MOBILE_APP) if (KEXI_DEBUG_GUI) list(APPEND kexiutils_LIB_SRCS debuggui.cpp ) endif () endif () if(BUILD_TESTING) list(APPEND kexiutils_LIB_SRCS KexiTestHandler.cpp ) endif() kexi_add_library(kexiutils SHARED ${kexiutils_LIB_SRCS}) set(kexiutils_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR} ) target_include_directories(kexiutils PUBLIC "$" ) target_link_libraries(kexiutils PUBLIC KF5::IconThemes KF5::WidgetsAddons KF5::ConfigWidgets # KStandardAction KColorScheme KF5::I18n KF5::ItemViews # KCategorizedView KCategoryDrawer KDb - PRIVATE - KF5::KIOFileWidgets # KFileWidget::getStartUrl(), KRecentDirs ) if(SHOULD_BUILD_KEXI_DESKTOP_APP) target_link_libraries(kexiutils PUBLIC KF5::KIOWidgets #for KRun... + PRIVATE + KF5::KIOFileWidgets # KFileWidget::getStartUrl(), KRecentDirs ) #target_link_libraries(kexiutils LINK_INTERFACE_LIBRARIES KF5::KIOWidgets) endif() if(BUILD_TESTING) target_link_libraries(kexiutils PRIVATE Qt5::Test ) endif() generate_export_header(kexiutils) install(TARGETS kexiutils ${INSTALL_TARGETS_DEFAULT_ARGS}) if(FALSE) # TODO: install when we move to independent place install( FILES tristate.h utils.h kexiutils_export.h kexiutils_global.h InternalPropertyMap.h SmallToolButton.h FlowLayout.h kmessagewidget.h KexiContextMessage.h KexiTitleLabel.h KexiAssistantPage.h KexiAssistantWidget.h KexiAnimatedLayout.h DESTINATION ${INCLUDE_INSTALL_DIR}/kexiutils COMPONENT Devel) endif() if(BUILD_TESTING) add_subdirectory(tests) endif() diff --git a/src/kexiutils/utils.cpp b/src/kexiutils/utils.cpp index ee01c21c1..f998eadd7 100644 --- a/src/kexiutils/utils.cpp +++ b/src/kexiutils/utils.cpp @@ -1,1199 +1,1206 @@ /* 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 #ifndef KEXI_MOBILE -#include +#include +#include #include #include +#include #endif #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(QWidget *widget) : startedOrActive(false), m_widget(widget), m_handleWidget(widget) { m_timer.setSingleShot(true); connect(&m_timer, SIGNAL(timeout()), this, SLOT(show())); } void DelayedCursorHandler::start(bool noDelay) { startedOrActive = true; m_timer.start(noDelay ? 0 : 1000); } void DelayedCursorHandler::stop() { startedOrActive = false; m_timer.stop(); if (m_handleWidget && m_widget) { m_widget->unsetCursor(); } else { QApplication::restoreOverrideCursor(); } } void DelayedCursorHandler::show() { const QCursor waitCursor(Qt::WaitCursor); if (m_handleWidget && m_widget) { m_widget->unsetCursor(); m_widget->setCursor(waitCursor); } else { QApplication::restoreOverrideCursor(); QApplication::setOverrideCursor(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) : m_handler(nullptr) { setWaitCursor(noDelay); } WaitCursor::WaitCursor(QWidget *widget, bool noDelay) { DelayedCursorHandler *handler = new DelayedCursorHandler(widget); handler->start(noDelay); m_handler = handler; } WaitCursor::~WaitCursor() { if (m_handler) { qobject_cast(m_handler)->stop(); delete m_handler; } else { 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, int filter) { QStringList result; const QMetaEnum enumerator(metaProperty.enumerator()); const int count = enumerator.keyCount(); int total = 0; for (int i = 0; i < count; i++) { if (filter == INT_MIN) { result.append(QString::fromLatin1(enumerator.key(i))); } else { const int v = enumerator.value(i); if ((v & filter) && !(total & v)) { // !(total & v) is a protection adding against masks result.append(QString::fromLatin1(enumerator.key(i))); total |= v; } } } return result; } //! @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); 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); if (QDialog::Accepted == dialog->exec()) { return dialog->selectedUrls().value(0); } else { return QUrl(); } } +#ifndef KEXI_MOBILE QUrl KexiUtils::getStartUrl(const QUrl &startDirOrVariable, QString *recentDirClass) { QUrl result; if (recentDirClass) { result = KFileWidget::getStartUrl(startDirOrVariable, *recentDirClass); // Fix bug introduced by Kexi 3.0.x in KexiFileWidget: remove file protocol from path // (the KRecentDirs::add(.., dir.url()) call was invalid because of prepended protocol) const QString protocol("file:/"); if (result.path().startsWith(protocol) && !result.path().startsWith(protocol + '/')) { result.setPath(result.path().mid(protocol.length() - 1)); } } else { qWarning() << "Missing recentDirClass"; } return result; } void KexiUtils::addRecentDir(const QString &fileClass, const QString &directory) { KRecentDirs::add(fileClass, directory); } +#endif bool KexiUtils::askForFileOverwriting(const QString& filePath, QWidget *parent) { QFileInfo fi(filePath); if (!fi.exists()) { return true; } const KMessageBox::ButtonCode res = KMessageBox::warningYesNo(parent, xi18nc("@info", "The file %1 already exists." "Do you want to overwrite it?", QDir::toNativeSeparators(filePath)), QString(), KStandardGuiItem::overwrite(), KStandardGuiItem::no()); return res == KMessageBox::Yes; } 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) { -#ifndef KEXI_MOBILE +#ifdef KEXI_MOBILE + //! @todo + Q_UNUSED(url) + Q_UNUSED(parent) + Q_UNUSED(options) +#else 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::Notify | 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::RunFlags(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:; } #endif 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()), isKDE(name == QStringLiteral("KDE")) { } const QByteArray name; const bool isKDE; 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; } bool KexiUtils::isKDEDesktopSession() { return s_detectedDesktopSession->isKDE; } bool KexiUtils::shouldUseNativeDialogs() { #if defined Q_OS_UNIX && !defined Q_OS_MACOS return isKDEDesktopSession() || detectedDesktopSession().isEmpty(); #else return true; #endif } //! @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 program = QString::fromLatin1("xfconf-query"); const QString programPath = QStandardPaths::findExecutable(program); const QStringList arguments{ program, "-c", channel, "-p", property }; QProcess process; process.start(programPath, arguments);//, QIODevice::ReadOnly | QIODevice::Text); qDebug() << "a" << int(process.exitCode()); if (!process.waitForStarted()) { qWarning() << "Count not execute command" << programPath << arguments << "error:" << process.error(); return QByteArray(); } const int exitCode = process.exitCode(); // !=0 e.g. for "no such property or channel" if (exitCode != 0 || !process.waitForFinished() || process.exitStatus() != QProcess::NormalExit) { qWarning() << "Count not finish command" << programPath << arguments << "error:" << process.error() << "exit code:" << exitCode << "exit status:" << process.exitStatus(); return QByteArray(); } if (ok) { *ok = true; } result = process.readAll(); result.chop(1); return result; } #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); } } QDebug operator<<(QDebug dbg, const QDomNode &node) { QString s; QTextStream str(&s, QIODevice::WriteOnly); node.save(str, 2); dbg << qPrintable(s); return dbg; } diff --git a/src/kexiutils/utils.h b/src/kexiutils/utils.h index 7eb13e7c8..221727440 100644 --- a/src/kexiutils/utils.h +++ b/src/kexiutils/utils.h @@ -1,708 +1,710 @@ /* This file is part of the KDE project Copyright (C) 2003-2017 Jarosław Staniek Contains code from kglobalsettings.h: Copyright (C) 2000, 2006 David Faure Copyright (C) 2008 Friedrich W. H. Kossebau Contains code from kdialog.h: 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. */ #ifndef KEXIUTILS_UTILS_H #define KEXIUTILS_UTILS_H #include "kexiutils_export.h" #include "kexi_global.h" #include #include #include #include #include #include #include #include #include class QColor; class QDomNode; class QMetaProperty; class QLayout; class QLineEdit; class KLocalizedString; //! @short General Utils namespace KexiUtils { //! \return true if parent of \a o that is of type \a className or false otherwise inline bool parentIs(QObject* o, const char* className = 0) { if (!o) return false; while ((o = o->parent())) { if (o->inherits(className)) return true; } return false; } //! \return parent object of \a o that is of type \a type or 0 if no such parent template inline type findParentByType(QObject* o) { if (!o) return 0; while ((o = o->parent())) { if (dynamic_cast< type >(o)) return dynamic_cast< type >(o); } return 0; } /*! \return first found child of \a o, inheriting \a className. If objName is 0 (the default), all object names match. Returned pointer type is casted. */ KEXIUTILS_EXPORT QObject* findFirstQObjectChild(QObject *o, const char* className, const char* objName); /*! \return first found child of \a o, that inherit \a className. If \a objName is 0 (the default), all object names match. Returned pointer type is casted. */ template inline type findFirstChild(QObject *o, const char* className, const char* objName = 0) { return ::qobject_cast< type >(findFirstQObjectChild(o, className, objName)); } //! Finds property for name \a name and object \a object returns it index; //! otherwise returns a null QMetaProperty. KEXIUTILS_EXPORT QMetaProperty findPropertyWithSuperclasses(const QObject* object, const char* name); //! \return true if \a object object is of class name \a className inline bool objectIsA(QObject* object, const char* className) { return 0 == qstrcmp(object->metaObject()->className(), className); } //! \return true if \a object object is of the class names inside \a classNames KEXIUTILS_EXPORT bool objectIsA(QObject* object, const QList& classNames); //! \return a list of methods for \a metaObject meta object. //! The methods are of type declared in \a types and have access declared //! in \a access. KEXIUTILS_EXPORT QList methodsForMetaObject( const QMetaObject *metaObject, QFlags types = QFlags(QMetaMethod::Method | QMetaMethod::Signal | QMetaMethod::Slot), QFlags access = QFlags(QMetaMethod::Private | QMetaMethod::Protected | QMetaMethod::Public)); //! Like \ref KexiUtils::methodsForMetaObject() but includes methods from all //! parent meta objects of the \a metaObject. KEXIUTILS_EXPORT QList methodsForMetaObjectWithParents( const QMetaObject *metaObject, QFlags types = QFlags(QMetaMethod::Method | QMetaMethod::Signal | QMetaMethod::Slot), QFlags access = QFlags(QMetaMethod::Private | QMetaMethod::Protected | QMetaMethod::Public)); //! \return a list with all this class's properties. KEXIUTILS_EXPORT QList propertiesForMetaObject( const QMetaObject *metaObject); //! \return a list with all this class's properties including thise inherited. KEXIUTILS_EXPORT QList propertiesForMetaObjectWithInherited( const QMetaObject *metaObject); //! \return a list of enum keys for meta property \a metaProperty. //! If @a filter is not INT_MIN, the method only returns enum keys that overlap with filter //! and are not combination of other keys. KEXIUTILS_EXPORT QStringList enumKeysForProperty(const QMetaProperty &metaProperty, int filter = INT_MIN); //! Convert a list @a list of @a SourceType type to another list of @a DestinationType //! type using @a convertMethod function /*! Example: @code QList list = ....; QStringList result = KexiUtils::convertTypesUsingFunction(list); @endcode */ template QList convertTypesUsingFunction(const QList &list) { QList result; foreach(const SourceType &element, list) { result.append(ConvertFunction(element)); } return result; } //! Convert a list @a list of @a SourceType type to another list of @a DestinationType //! type using @a convertMethod /*! Example: @code QVariantList list = ....; QStringList result = KexiUtils::convertTypesUsingMethod(list); @endcode */ template QList convertTypesUsingMethod(const QList &list) { QList result; foreach(const SourceType &element, list) { result.append((element.*ConvertMethod)()); } return result; } /*! Sets "wait" cursor with 1 second delay (or 0 seconds if noDelay is true). Does nothing if the application has no GUI enabled. (see KApplication::guiEnabled()) */ KEXIUTILS_EXPORT void setWaitCursor(bool noDelay = false); /*! Remove "wait" cursor previously set with \a setWaitCursor(), even if it's not yet visible. Does nothing if the application has no GUI enabled. (see KApplication::guiEnabled()) */ KEXIUTILS_EXPORT void removeWaitCursor(); /*! Helper class. Allocate it in your code block as follows: KexiUtils::WaitCursor wait; .. and wait cursor will be visible (with one second delay) until you're in this block, without a need to call removeWaitCursor() before exiting the block. Does nothing if the application has no GUI enabled. (see KApplication::guiEnabled()) */ class KEXIUTILS_EXPORT WaitCursor { public: //! Wait cursor handler for application explicit WaitCursor(bool noDelay = false); //! @overload //! Wait cursor handler for widget @a widget explicit WaitCursor(QWidget *widget, bool noDelay = false); ~WaitCursor(); private: QObject *m_handler; }; /*! Helper class. Allocate it in your code block as follows: KexiUtils::WaitCursorRemover remover; .. and the wait cursor will be hidden unless you leave this block, without a need to call setWaitCursor() before exiting the block. After leaving the codee block, the cursor will be visible again, if it was visible before creating the WaitCursorRemover object. Does nothing if the application has no GUI enabled. (see KApplication::guiEnabled()) */ class KEXIUTILS_EXPORT WaitCursorRemover { public: WaitCursorRemover(); ~WaitCursorRemover(); private: bool m_reactivateCursor; }; /*! Creates a modal file dialog which returns the selected url of image filr to open or an empty string if none was chosen. Like KFileDialog::getImageOpenUrl(). */ //! @todo KEXI3 add equivalent of kfiledialog:/// KEXIUTILS_EXPORT QUrl getOpenImageUrl(QWidget *parent = 0, const QString &caption = QString(), const QUrl &directory = QUrl()); /*! Creates a modal file dialog with returns the selected url of image file to save or an empty string if none was chosen. Like KFileDialog::getSaveUrl(). */ //! @todo KEXI3 add equivalent of kfiledialog:/// KEXIUTILS_EXPORT QUrl getSaveImageUrl(QWidget *parent = 0, const QString &caption = QString(), const QUrl &directory = QUrl()); +#ifndef KEXI_MOBILE /** * This method implements the logic to determine the user's default directory * to be listed. E.g. the documents directory, home directory or a recently * used directory. * * Use instead of KFileWidget::getStartUrl(const QUrl &startDir, QString &recentDirClass). * * @param startDir A URL specifying the initial directory, or using the * @c kfiledialog:/// syntax to specify a last used * directory. If this URL specifies a file name, it is * ignored. Refer to the KFileWidget::KFileWidget() * documentation for the @c kfiledialog:/// URL syntax. * @param recentDirClass If the @c kfiledialog:/// syntax is used, this * will return the string to be passed to KRecentDirs::dir() and * KRecentDirs::add(). * @return The URL that should be listed by default (e.g. by KFileDialog or * KDirSelectDialog). * * @see KFileWidget::KFileWidget() * @since 3.1.0 * @todo Make it independent of KIOFileWidgets */ KEXIUTILS_EXPORT QUrl getStartUrl(const QUrl &startDirOrVariable, QString *recentDirClass); /** * Associates @p directory with @p fileClass * * Use instead of KRecentDirs::add() * * @since 3.1.0 * @todo Make it independent of KIOFileWidgets */ KEXIUTILS_EXPORT void addRecentDir(const QString &fileClass, const QString &directory); +#endif // !KEXI_MOBILE /*! Displays a "The file %1 already exists. Do you want to overwrite it?" Yes/No message box. @a parent is used as a parent of the message box. @return @c true if @a filePath file does not exist or user has agreed to overwrite it; returns @c false if user does not agree to overwrite it. */ KEXIUTILS_EXPORT bool askForFileOverwriting(const QString& filePath, QWidget *parent = nullptr); /*! A global setting for minimal readable font. This can be used in dockers, rulers and other places where space is at a premium. @see QFontDatabase::systemFont(QFontDatabase::SmallestReadableFont). @todo Add integration with KDE platform theme (how to detect it?); for now we don't assume it's installed */ KEXIUTILS_EXPORT QFont smallestReadableFont(); /*! \return a color being a result of blending \a c1 with \a c2 with \a factor1 and \a factor1 factors: (c1*factor1+c2*factor2)/(factor1+factor2). */ KEXIUTILS_EXPORT QColor blendedColors(const QColor& c1, const QColor& c2, int factor1 = 1, int factor2 = 1); /*! \return a contrast color for a color \a c: If \a c is light color, darker color created using c.dark(200) is returned; otherwise lighter color created using c.light(200) is returned. */ KEXIUTILS_EXPORT QColor contrastColor(const QColor& c); /*! \return a lighter color for a color \a c and a factor \a factor. For colors like Qt::red or Qt::green where hue and saturation are near to 255, hue is decreased so the result will be more bleached. For black color the result is dark gray rather than black. */ KEXIUTILS_EXPORT QColor bleachedColor(const QColor& c, int factor); /*! \return icon set computed as a result of colorizing \a icon pixmap with \a role color of \a palette palette. This function is useful for displaying monochromed icons on the list view or table view header, to avoid bloat, but still have the color compatible with accessibility settings. */ KEXIUTILS_EXPORT QIcon colorizeIconToTextColor(const QPixmap& icon, const QPalette& palette, QPalette::ColorRole role = QPalette::ButtonText); /*! Replaces colors in pixmap @a original using @a color color. Used for coloring bitmaps that have to reflect the foreground color. */ KEXIUTILS_EXPORT void replaceColors(QPixmap* original, const QColor& color); /*! Replaces colors in image @a original using @a color color. Used for coloring bitmaps that have to reflect the foreground color. */ KEXIUTILS_EXPORT void replaceColors(QImage* original, const QColor& color); /*! @return true if curent color scheme is light. Lightness of window background is checked to measure this. */ KEXIUTILS_EXPORT bool isLightColorScheme(); /*! @return alpha value for dimmed color (150). */ KEXIUTILS_EXPORT int dimmedAlpha(); /*! @return palette @a pal with dimmed color @a role. @see dimmedAlpha() */ KEXIUTILS_EXPORT QPalette paletteWithDimmedColor(const QPalette &pal, QPalette::ColorGroup group, QPalette::ColorRole role); /*! @overload paletteWithDimmedColor(const QPalette &, QPalette::ColorGroup, QPalette::ColorRole) */ KEXIUTILS_EXPORT QPalette paletteWithDimmedColor(const QPalette &pal, QPalette::ColorRole role); /*! @return palette altered for indicating "read only" flag. */ KEXIUTILS_EXPORT QPalette paletteForReadOnly(const QPalette &palette); /*! Convenience function that sets background color @a color for widget @a widget. "autoFillBackground" property is set to true for the widget. Background color role is obtained from QWidget::backgroundRole(). */ KEXIUTILS_EXPORT void setBackgroundColor(QWidget *widget, const QColor &color); /*! \return empty (fully transparent) pixmap that can be used as a place for icon of size \a iconGroup */ KEXIUTILS_EXPORT QPixmap emptyIcon(KIconLoader::Group iconGroup); #ifdef KEXI_DEBUG_GUI //! Creates debug window for convenient debugging output KEXIUTILS_EXPORT QWidget *createDebugWindow(QWidget *parent); //! Connects push button action to \a receiver and its \a slot. This allows to execute debug-related actions //! using buttons displayed in the debug window. KEXIUTILS_EXPORT void connectPushButtonActionForDebugWindow(const char* actionName, const QObject *receiver, const char* slot); #endif //! Sets focus for widget \a widget with reason \a reason. KEXIUTILS_EXPORT void setFocusWithReason(QWidget* widget, Qt::FocusReason reason); //! Unsets focus for widget \a widget with reason \a reason. KEXIUTILS_EXPORT void unsetFocusWithReason(QWidget* widget, Qt::FocusReason reason); //! If the application's layout direction, swaps left and right margins. //! @see QGuiApplication::isRightToLeft() void adjustIfRtl(QMargins *margins); //! Draws pixmap @a pixmap on painter @a p using predefined parameters. //! Used in KexiDBImageBox and KexiBlobTableEdit. KEXIUTILS_EXPORT void drawPixmap(QPainter* p, const QMargins& margins, const QRect& rect, const QPixmap& pixmap, Qt::Alignment alignment, bool scaledContents, bool keepAspectRatio, Qt::TransformationMode transformMode = Qt::FastTransformation); //! Scales pixmap @a pixmap on painter @a p using predefined parameters. //! Used in KexiDBImageBox and KexiBlobTableEdit. KEXIUTILS_EXPORT QPixmap scaledPixmap(const QMargins& margins, const QRect& rect, const QPixmap& pixmap, QPoint* pos, Qt::Alignment alignment, bool scaledContents, bool keepAspectRatio, Qt::TransformationMode transformMode = Qt::FastTransformation); //! This function should be used instead of QPixmap::loadFromData(). /** Loads a pixmap from @a data into @a pixmap. First tries to detect format, on failure * tries to load most common formats: png, jpg, bmp, tif. Then tries to load any of format * returned by QImageReader::supportedImageFormats(). * If @a format is provided, only this format is tried. * @return on success. * @note This function exists because QPixmap::loadFromData() not always works when there * are broken image format plugins installed (as it was the case with KRA plugin). * @todo Idea: Support while/black list of supported image formats. It would be useful * for security reasons because files can be loaded from remote locations. * @todo For the black/white list an enum describing local/remote data source is needed. */ KEXIUTILS_EXPORT bool loadPixmapFromData(QPixmap *pixmap, const QByteArray &data, const char *format = nullptr); //! A helper for automatic deleting of contents of containers. template class ContainerDeleter { public: explicit ContainerDeleter(Container& container) : m_container(container) {} ~ContainerDeleter() { clear(); } void clear() { qDeleteAll(m_container); m_container.clear(); } private: Container& m_container; }; /*! A modified QFrame which sets up sunken styled panel frame style depending on the current widget style. The widget also reacts on style changes. */ class KEXIUTILS_EXPORT KTextEditorFrame : public QFrame { Q_OBJECT public: explicit KTextEditorFrame(QWidget * parent = 0, Qt::WindowFlags f = 0); protected: virtual void changeEvent(QEvent *event); }; /** * Returns the number of pixels that should be used between a * dialog edge and the outermost widget(s) according to the KDE standard. * * Copied from QDialog. * * @deprecated Use the style's pixelMetric() function to query individual margins. * Different platforms may use different values for the four margins. */ KEXIUTILS_EXPORT int marginHint(); /** * Returns the number of pixels that should be used between * widgets inside a dialog according to the KDE standard. * * Copied from QDialog. * * @deprecated Use the style's layoutSpacing() function to query individual spacings. * Different platforms may use different values depending on widget types and pairs. */ KEXIUTILS_EXPORT int spacingHint(); /*! Sets KexiUtils::marginHint() margins and KexiUtils::spacingHint() spacing for the layout @a layout. */ KEXIUTILS_EXPORT void setStandardMarginsAndSpacing(QLayout *layout); /*! Sets the same @a value for layout @a layout margins. */ KEXIUTILS_EXPORT void setMargins(QLayout *layout, int value); //! sometimes we leave a space in the form of empty QFrame and want to insert here //! a widget that must be instantiated by hand. //! This macro inserts a widget \a what into a frame \a where. #define GLUE_WIDGET(what, where) \ { QVBoxLayout *lyr = new QVBoxLayout(where); \ lyr->addWidget(what); } //! A tool for setting temporary value for boolean variable. /*! After destruction of the instance, the variable is set back to the original value. This class is useful in recursion guards. To use it, declare class atrribute of type bool and block it, e.g.: @code bool m_myNonRecursiveFunctionEnabled; // ... set m_myNonRecursiveFunctionEnabled initially to true void myNonRecursiveFunctionEnabled() { if (!m_myNonRecursiveFunctionEnabled) return; KexiUtils::BoolBlocker guard(&m_myNonRecursiveFunctionEnabled, false); // function's body guarded against recursion... } @endcode */ class KEXIUTILS_EXPORT BoolBlocker { public: inline BoolBlocker(bool *var, bool tempValue) : v(var), origValue(*var) { *var = tempValue; } inline ~BoolBlocker() { *v = origValue; } private: bool *v; bool origValue; }; /*! This helper function install an event filter on @a object and all of its children, directed to @a filter. */ KEXIUTILS_EXPORT void installRecursiveEventFilter(QObject *object, QObject *filter); /*! This helper function removes an event filter installed before on @a object and all of its children. */ KEXIUTILS_EXPORT void removeRecursiveEventFilter(QObject *object, QObject *filter); //! Blocks paint events on specified widget. /*! Works recursively. Useful when widget should be hidden without changing geometry it takes. */ class KEXIUTILS_EXPORT PaintBlocker : public QObject { Q_OBJECT public: explicit PaintBlocker(QWidget* parent); void setEnabled(bool set); bool enabled() const; protected: virtual bool eventFilter(QObject* watched, QEvent* event); private: bool m_enabled; }; /*! * \short Options for opening of hyperlinks * \sa openHyperLink() */ class KEXIUTILS_EXPORT OpenHyperlinkOptions : public QObject { Q_OBJECT public: /*! * A tool used for opening hyperlinks */ enum HyperlinkTool{ DefaultHyperlinkTool, /*!< Default tool for a given type of the hyperlink */ BrowserHyperlinkTool, /*!< Opens hyperlink in a browser */ MailerHyperlinkTool /*!< Opens hyperlink in a default mailer */ }; Q_ENUM(HyperlinkTool) OpenHyperlinkOptions() : tool(DefaultHyperlinkTool) , allowExecutable(false) , allowRemote(false) {} HyperlinkTool tool; bool allowExecutable; bool allowRemote; }; /*! * Opens the given \a url using \a options * It can fail if opening a given link is not possible or allowed. * @return true on success, cancelled if user has cancelled the opening and false on failure */ KEXIUTILS_EXPORT tristate openHyperLink(const QUrl &url, QWidget *parent, const OpenHyperlinkOptions &options); //! \return size of combo box arrow according to \a style /*! Application's style is the default. \see QStyle::SC_ComboBoxArrow */ KEXIUTILS_EXPORT QSize comboBoxArrowSize(QStyle *style = 0); //! Adds a dirty ("document modified") flag to @a text according to current locale. //! It is usually "*" character appended. KEXIUTILS_EXPORT void addDirtyFlag(QString *text); //! @return The name of the user's preferred encoding //! Based on KLocale::encoding() KEXIUTILS_EXPORT QByteArray encoding(); //! The desired level of effects on the GUI enum GraphicEffect { NoEffects = 0x0000, ///< GUI with no effects at all. GradientEffects = 0x0001, ///< GUI with only gradients enabled. SimpleAnimationEffects = 0x0002, ///< GUI with simple animations enabled. ComplexAnimationEffects = 0x0006 ///< GUI with complex animations enabled. ///< Note that ComplexAnimationsEffects implies SimpleAnimationEffects. }; Q_DECLARE_FLAGS(GraphicEffects, GraphicEffect) //! @return the desired level of effects on the GUI. //! @note A copy of KGlobalSettings::graphicEffectsLevel() needed for porting from kdelibs4. KEXIUTILS_EXPORT GraphicEffects graphicEffectsLevel(); //! @return the inactive titlebar background color //! @note A copy of KGlobalSettings::inactiveTitleColor() needed for porting from kdelibs4. KEXIUTILS_EXPORT QColor inactiveTitleColor(); //! @return the inactive titlebar text (foreground) color //! @note A copy of KGlobalSettings::inactiveTextColor() needed for porting from kdelibs4. KEXIUTILS_EXPORT QColor inactiveTextColor(); //! @return the active titlebar background color //! @note A copy of KGlobalSettings::activeTitleColor() needed for porting from kdelibs4. KEXIUTILS_EXPORT QColor activeTitleColor(); //! @return the active titlebar text (foreground) color //! @note A copy of KGlobalSettings::activeTextColor() needed for porting from kdelibs4. KEXIUTILS_EXPORT QColor activeTextColor(); //! @return Paper White color, see https://techbase.kde.org/Projects/Usability/HIG/Color inline QColor paperWhite() { return QColor(0xfcfcfc); } //! @return Charcoal Grey color, see https://techbase.kde.org/Projects/Usability/HIG/Color inline QColor charcoalGrey() { return QColor(0x31363b); } //! @return Shade Black color, see https://techbase.kde.org/Projects/Usability/HIG/Color inline QColor shadeBlack() { return QColor(0x232629); } /*! @return @c true if whether the app runs in a single click mode (the default). @c false if returned if the app runs in double click mode. The flag is checked in two stages. Stage 1. Application config file's "SingleClickOpensItem" value in "MainWindow" group is checked. If it exists, the value is returned. On Windows if it does not exist, @c true is returned, on other systems Stage 2 checking is performed. Stage 2. For Qt < 5.5 this information is taken from @a widget widget's style. If there is no widget specified, QApplication::style() is used. For Qt >= 5.5 the result is equal to QApplication::styleHints()->singleClickActivation() and @a widget is ignored. @note This is a replacement for bool KGlobalSettings::singleClick(). */ KEXIUTILS_EXPORT bool activateItemsOnSingleClick(QWidget *widget = 0); /** * Detects name of desktop session based on environment variables. * * Possible value are like GNOME, XFCE, KDE. They are always uppercase. Following environment * variables are used: XDG_SESSION_DESKTOP. XDG_CURRENT_DESKTOP, DESKTOP_SESSION, KDE_FULL_SESSION, * GNOME_DESKTOP_SESSION_ID. * * @return empty string if no desktop session was detected or sessions are not supported for the * running OS (Windows, macOS, non-desktop OS). * * @note use QApplication::styleHints() if possible. */ KEXIUTILS_EXPORT QByteArray detectedDesktopSession(); /** * @return true is this is a KDE / Plasma desktop session * * Detection is based on detectedDesktopSession(). */ KEXIUTILS_EXPORT bool isKDEDesktopSession(); /** * @brief Returns @c true if native operating system's dialogs should be used * * Returns @c false if Qt's standard dialogs should be used instead of the operating system native * dialogs. Can be used with QColorDialog, QFileDialog and QFontDialog. * * Depends on the curent desktop in use: * - on Unix (other than macOS) returns @c true if isKDEDesktopSession() is @c true or if desktop * session can't be detected, @c false for other desktops * - @c true for all other operating systems, i.e. for MS Windows, macOS, etc. * * @todo Share this code with KReport and Kexi */ KEXIUTILS_EXPORT bool shouldUseNativeDialogs(); /** * @enum CaptionFlag * Used to specify how to construct a window caption * * @value AppNameCaption Indicates that the method shall include * the application name when making the caption string. * @value ModifiedCaption Causes a 'modified' sign will be included in the * returned string. This is useful when indicating that a file is * modified, i.e., it contains data that has not been saved. */ enum CaptionFlag { NoCaptionFlags = 0, AppNameCaption = 1, ModifiedCaption = 2 }; Q_DECLARE_FLAGS(CaptionFlags, CaptionFlag) /** * Builds a caption that contains the application name along with the * userCaption using a standard layout. * * To make a compliant caption for your window, simply do: * @p setWindowTitle(makeStandardCaption(yourCaption)); * * To ensure that the caption is appropriate to the desktop in which the * application is running, pass in a pointer to the window the caption will * be applied to. * * @param userCaption The caption string you want to display in the * window caption area. Do not include the application name! * @param flags * @return the created caption * Based on KDialog::makeStandardCaption() */ KEXIUTILS_EXPORT QString makeStandardCaption(const QString &userCaption, CaptionFlags flags = AppNameCaption); /** * Return rich text for @a string. Equivalent of KLocalizedString::toString(Kuit::RichText) * but and is removed so the result can be used as %* argument in other string. */ KEXIUTILS_EXPORT QString localizedStringToHtmlSubstring(const KLocalizedString& string); /** * @return @c true if text cursor is at the end of the line edit @a lineEdit. * If the @a lineEdit edit has input mask, cursor is at the end if it's at position * lineEdit->displayText().length() - 1 or further. If the @a lineEdit has no input mask, cursor * is at the end if it's at position lineEdit->text().length() or further. */ KEXIUTILS_EXPORT bool cursorAtEnd(const QLineEdit *lineEdit); } //namespace KexiUtils /** * Writes the DOM tree to the stream and returns a reference to the stream. */ KEXIUTILS_EXPORT QDebug operator<<(QDebug dbg, const QDomNode &node); #endif //KEXIUTILS_UTILS_H diff --git a/src/mobile/KexiMobileMainWindow.cpp b/src/mobile/KexiMobileMainWindow.cpp index 89addf83f..fdacead46 100644 --- a/src/mobile/KexiMobileMainWindow.cpp +++ b/src/mobile/KexiMobileMainWindow.cpp @@ -1,396 +1,401 @@ /** This file is part of the KDE project * * Copyright (C) 2011 Adam Pigg * * 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 "KexiMobileMainWindow.h" #include "KexiMobileWidget.h" #include "KexiMobileToolbar.h" #include "KexiMobileNavigator.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include KexiMobileMainWindow::KexiMobileMainWindow() { m_mobile = new KexiMobileWidget(0); m_toolbar = new KexiMobileToolbar(this); m_layout = new QHBoxLayout(this); //! part info has to be collected at this stage KexiPart::PartInfoList *partInfoList = Kexi::partManager().infoList(); Q_UNUSED(partInfoList) m_openFileAction = new QAction(koIcon("document-open"), "Open", this); connect(m_openFileAction, SIGNAL(triggered(bool)), this, SLOT(slotOpenDatabase())); menuBar()->addAction(m_openFileAction); m_layout->addWidget(m_mobile); m_layout->setSpacing(2); setFixedSize(800,480); setCentralWidget(m_mobile); addToolBar(Qt::BottomToolBarArea, m_toolbar); connect(m_toolbar, SIGNAL(pageNavigator()), m_mobile, SLOT(showNavigator())); connect(m_mobile->navigator(), SIGNAL(openItem(KexiPart::Item*)), this, SLOT(openObject(KexiPart::Item*))); } void KexiMobileMainWindow::setupToolbar() { } KexiMobileMainWindow::~KexiMobileMainWindow() {} void KexiMobileMainWindow::slotOpenDatabase() { QString fileName; fileName = QFileDialog::getOpenFileName(this, xi18n("Open Database"), "", xi18n("Database Files (*.kexi)")); if (!fileName.isNull()) { KexiProject *proj = openProject(QUrl::fromLocalFile(fileName)); if (proj) { m_project = proj; m_mobile->databaseOpened(proj); } else { qWarning() << "Project not returned"; } } } KexiProject *KexiMobileMainWindow::openProject(const QUrl &url) { KDbDriverManager driverManager; KDbDriver *driver = 0; QMimeDatabase db; QMimeType mime = db.mimeTypeForUrl(url); QString driverName = driverManager.lookupByMime(mime.name()); driver = driverManager.driver(driverName.toLower()); qDebug() << driverManager.driverNames(); qDebug() << driverName; KexiProjectData *project_data = new KexiProjectData; project_data->setDatabaseName(url.path()); qDebug() << driver; if (driver && driver->isFileDriver()) { project_data->connectionData()->setFileName(url.path()); } project_data->connectionData()->driverName = driverName; KexiProject *project = new KexiProject(*project_data); return project; } KexiWindow* KexiMobileMainWindow::openObject(KexiPart::Item* item) { bool cancelled; KexiWindow* win = openObject(item, Kexi::DataViewMode, &cancelled); if (!cancelled) return win; return 0; } KexiWindow * KexiMobileMainWindow::openObject(KexiPart::Item* item, Kexi::ViewMode viewMode, bool *openingCancelled, QMap* staticObjectArgs, QString* errorMessage) { Q_ASSERT(openingCancelled); qDebug() << "KexiMobileMainWindow::openObject"; KexiWindow *window = 0; if (!openingAllowed(item, viewMode, errorMessage)) { if (errorMessage) *errorMessage = xi18nc( "@info opening is not allowed in \"data view/design view/text view\" mode", "opening is not allowed in %1 mode", Kexi::nameForViewMode(viewMode)); *openingCancelled = true; return 0; } qDebug() << m_project << item; if (!m_project || !item) return 0; //!TODO Move this to KexiUtils::WaitCursor #ifdef Q_WS_MAEMO_5 setAttribute(Qt::WA_Maemo5ShowProgressIndicator, true); #endif //Create the window window = m_project->openObject(m_mobile, item, viewMode, staticObjectArgs); if (window) { m_mobile->setActiveObject(window); } m_toolbar->setRecordHandler(dynamic_cast(window->selectedView())); #if 0 if (window && !alreadyOpened) { // window->setParent(d->tabWidget); // KexiWindow* previousWindow = currentWindow(); // Call switchToViewMode() and propertySetSwitched() again here because // this is the time when then new window is the current one - previous call did nothing. switchToViewMode(*window, window->currentViewMode()); currentWindow()->selectedView()->propertySetSwitched(); // activeWindowChanged(window, previousWindow); } #endif #ifdef Q_WS_MAEMO_5 setAttribute(Qt::WA_Maemo5ShowProgressIndicator, false); #endif return window; } bool KexiMobileMainWindow::openingAllowed(KexiPart::Item* item, Kexi::ViewMode viewMode, QString* errorMessage) { qDebug() << viewMode; //! @todo this can be more complex once we deliver ACLs... //1 Load the part //2 Return true if the part loads AND the part supports the view mode AND the viewmode is Data KexiPart::Part * part = Kexi::partManager().part(item); if (!part) { if (errorMessage) { *errorMessage = Kexi::partManager().errorMsg(); } } qDebug() << part << item->pluginId(); /*if (part) qDebug() << item->pluginId() << part->supportedUserViewModes();*/ return part /*&& (part->supportedUserViewModes() & viewMode)*/ && (viewMode == Kexi::DataViewMode); } //========KexiMainWindowIFace==================== void KexiMobileMainWindow::acceptProjectClosingRequested(bool *cancel) { } void KexiMobileMainWindow::acceptPropertySetEditing() { } KActionCollection* KexiMobileMainWindow::actionCollection() const { return 0; } void KexiMobileMainWindow::addToolBarAction(const QString& toolBarName, QAction* action) { } QList< QAction* > KexiMobileMainWindow::allActions() const { return QList(); } void KexiMobileMainWindow::appendWidgetToToolbar(const QString& name, QWidget* widget) { } void KexiMobileMainWindow::beforeProjectClosing() { } tristate KexiMobileMainWindow::closeObject(KexiPart::Item* item) { return true; } tristate KexiMobileMainWindow::closeWindow(KexiWindow* window) { return true; } KexiWindow* KexiMobileMainWindow::currentWindow() const { return 0; } tristate KexiMobileMainWindow::executeCustomActionForObject(KexiPart::Item* item, const QString& actionName) { return true; } QWidget* KexiMobileMainWindow::focusWidget() const { return 0; } tristate KexiMobileMainWindow::getNewObjectInfo(KexiPart::Item* partItem, KexiPart::Part* part, bool *allowOverwriting, const QString& messageWhenAskingForName) { return false; } void KexiMobileMainWindow::highlightObject(const QString& mime, const QString& name) { } bool KexiMobileMainWindow::newObject(KexiPart::Info* info, bool *openingCancelled) { return false; } KexiWindow* KexiMobileMainWindow::openObject(const QString& mime, const QString& name, Kexi::ViewMode viewMode, bool *openingCancelled, QMap< QString, QVariant >* staticObjectArgs) { return 0; } tristate KexiMobileMainWindow::printItem(KexiPart::Item* item) { return false; } tristate KexiMobileMainWindow::printPreviewForItem(KexiPart::Item* item) { return false; } KexiProject* KexiMobileMainWindow::project() { return m_project; } void KexiMobileMainWindow::projectClosed() { } void KexiMobileMainWindow::propertySetSwitched(KexiWindow* window, bool force, bool preservePrevSelection, bool sortedProperties, const QByteArray& propertyToSelect) { } void KexiMobileMainWindow::registerChild(KexiWindow* window) { } tristate KexiMobileMainWindow::saveObject(KexiWindow* window, const QString& messageWhenAskingForName, bool dontAsk) { return false; } void KexiMobileMainWindow::setWidgetVisibleInToolbar(QWidget* widget, bool visible) { } tristate KexiMobileMainWindow::showPageSetupForItem(KexiPart::Item* item) { return false; } void KexiMobileMainWindow::slotObjectRenamed(const KexiPart::Item& item, const QString& oldName) { } tristate KexiMobileMainWindow::switchToViewMode(KexiWindow& window, Kexi::ViewMode viewMode) { return false; } KToolBar* KexiMobileMainWindow::toolBar(const QString& name) const { return 0; } void KexiMobileMainWindow::updatePropertyEditorInfoLabel(const QString& textToDisplayForNullSet) { } bool KexiMobileMainWindow::userMode() const { return true; } -void KexiMobileMainWindow::addSearchableModel(KexiSearchableModel*) +void KexiMobileMainWindow::addSearchableModel(KexiSearchableModel *model) { + Q_UNUSED(model) +} +void KexiMobileMainWindow::removeSearchableModel(KexiSearchableModel *model) +{ + Q_UNUSED(model) } tristate KexiMobileMainWindow::getNewObjectInfo(KexiPart::Item*, const QString&, KexiPart::Part*, bool, bool*, const QString&) { return false; } KexiWindow* KexiMobileMainWindow::openedWindowFor(const KexiPart::Item*) { return 0; } tristate KexiMobileMainWindow::saveObject(KexiWindow*, const QString&, KexiMainWindowIface::SaveObjectOptions) { return false; } KexiUserFeedbackAgent* KexiMobileMainWindow::userFeedbackAgent() const { return 0; } diff --git a/src/mobile/KexiMobileMainWindow.h b/src/mobile/KexiMobileMainWindow.h index d6551b5b6..4e504bd72 100644 --- a/src/mobile/KexiMobileMainWindow.h +++ b/src/mobile/KexiMobileMainWindow.h @@ -1,98 +1,99 @@ /** This file is part of the KDE project * * Copyright (C) 2011 Adam Pigg * * 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. */ #ifndef KEXIMOBILE_H #define KEXIMOBILE_H #include #include #include class KexiMobileToolbar; class QHBoxLayout; class KexiMobileWidget; class KexiMobileMainWindow : public QMainWindow, public KexiMainWindowIface { Q_OBJECT public: KexiMobileMainWindow(); virtual ~KexiMobileMainWindow(); public Q_SLOTS: KexiWindow* openObject(KexiPart::Item* item); //KexiMainWindowIface Overrides virtual void acceptProjectClosingRequested(bool *cancel); virtual void acceptPropertySetEditing(); virtual KActionCollection* actionCollection() const; - virtual void addSearchableModel(KexiSearchableModel*); + void addSearchableModel(KexiSearchableModel *model) ; + void removeSearchableModel(KexiSearchableModel *model) override; virtual void addToolBarAction(const QString& toolBarName, QAction* action); virtual QList< QAction* > allActions() const; virtual void appendWidgetToToolbar(const QString& name, QWidget* widget); virtual void beforeProjectClosing(); virtual tristate closeObject(KexiPart::Item* item); virtual tristate closeWindow(KexiWindow* window); virtual KexiWindow* currentWindow() const; virtual tristate executeCustomActionForObject(KexiPart::Item* item, const QString& actionName); virtual QWidget* focusWidget() const; virtual tristate getNewObjectInfo(KexiPart::Item* partItem, KexiPart::Part* part, bool *allowOverwriting, const QString& messageWhenAskingForName = QString()); virtual void highlightObject(const QString& mime, const QString& name); virtual bool newObject(KexiPart::Info* info, bool *openingCancelled); virtual KexiWindow* openObject(KexiPart::Item* item, Kexi::ViewMode viewMode, bool *openingCancelled, QMap< QString, QVariant >* staticObjectArgs = 0, QString* errorMessage = 0); virtual KexiWindow* openObject(const QString& mime, const QString& name, Kexi::ViewMode viewMode, bool *openingCancelled, QMap< QString, QVariant >* staticObjectArgs = 0); virtual tristate printItem(KexiPart::Item* item); virtual tristate printPreviewForItem(KexiPart::Item* item); virtual KexiProject* project(); virtual void projectClosed(); virtual void propertySetSwitched(KexiWindow* window, bool force = false, bool preservePrevSelection = true, bool sortedProperties = false, const QByteArray& propertyToSelect = QByteArray()); virtual void registerChild(KexiWindow* window); virtual tristate saveObject(KexiWindow* window, const QString& messageWhenAskingForName = QString(), bool dontAsk = false); virtual tristate saveObject(KexiWindow*, const QString&, KexiMainWindowIface::SaveObjectOptions); virtual void setWidgetVisibleInToolbar(QWidget* widget, bool visible); virtual tristate showPageSetupForItem(KexiPart::Item* item); virtual void slotObjectRenamed(const KexiPart::Item& item, const QString& oldName); virtual tristate switchToViewMode(KexiWindow& window, Kexi::ViewMode viewMode); virtual KToolBar* toolBar(const QString& name) const; virtual void updatePropertyEditorInfoLabel(const QString& textToDisplayForNullSet = QString()); virtual KexiUserFeedbackAgent* userFeedbackAgent() const; virtual bool userMode() const; public Q_SLOTS: void slotOpenDatabase(); private: KexiMobileWidget *m_mobile; KexiMobileToolbar *m_toolbar; QAction *m_openFileAction; KexiProject *m_project; QHBoxLayout *m_layout; void setupToolbar(); KexiProject* openProject(const QUrl &url); bool openingAllowed(KexiPart::Item* item, Kexi::ViewMode viewMode, QString* errorMessage); }; #endif // KEXIMOBILE_H