File indexing completed on 2024-05-12 16:39:35

0001 /* This file is part of the KDE project
0002    Copyright (C) 2003-2012 Jarosław Staniek <staniek@kde.org>
0003 
0004    This program is free software; you can redistribute it and/or
0005    modify it under the terms of the GNU Library General Public
0006    License as published by the Free Software Foundation; either
0007    version 2 of the License, or (at your option) any later version.
0008 
0009    This program is distributed in the hope that it will be useful,
0010    but WITHOUT ANY WARRANTY; without even the implied warranty of
0011    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0012    Library General Public License for more details.
0013 
0014    You should have received a copy of the GNU Library General Public License
0015    along with this program; see the file COPYING.  If not, write to
0016    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
0017  * Boston, MA 02110-1301, USA.
0018 */
0019 
0020 #include "kexi.h"
0021 #include "KexiRecentProjects.h"
0022 #include "KexiMainWindowIface.h"
0023 #include "kexipartmanager.h"
0024 #include <KexiIcon.h>
0025 
0026 #include <KDb>
0027 #include <KDbMessageHandler>
0028 #include <KDbDriverManager>
0029 #include <KDbDriverMetaData>
0030 #include <KDbUtils>
0031 
0032 #include <KAboutData>
0033 #include <KMessageBox>
0034 #include <KIconTheme>
0035 
0036 #include <QPixmap>
0037 #include <QPixmapCache>
0038 #include <QLabel>
0039 #include <QMimeDatabase>
0040 #include <QMimeType>
0041 #include <QFileInfo>
0042 
0043 using namespace Kexi;
0044 
0045 //! used for speedup
0046 //! @internal
0047 class KexiInternal
0048 {
0049 public:
0050     static KexiInternal *_int;
0051 
0052     KexiInternal()
0053             : connset(0)
0054     {
0055     }
0056     ~KexiInternal() {
0057         delete connset;
0058     }
0059 
0060     static KexiInternal* self() {
0061         static bool created = false;
0062         if (!created) {
0063             _int = new KexiInternal;
0064             created = true;
0065         }
0066         return _int;
0067     }
0068 
0069     static void destroy() {
0070         delete _int;
0071         _int = 0;
0072     }
0073 
0074     KexiDBConnectionSet* connset;
0075     KexiRecentProjects recentProjects;
0076     KexiDBConnectionSet recentConnections;
0077     KDbDriverManager driverManager;
0078     KexiPart::Manager partManager;
0079 };
0080 
0081 KexiInternal *KexiInternal::_int = 0;
0082 
0083 KexiDBConnectionSet& Kexi::connset()
0084 {
0085     //delayed
0086     if (!KexiInternal::self()->connset) {
0087         //load stored set data, OK?
0088         KexiInternal::self()->connset = new KexiDBConnectionSet();
0089         KexiInternal::self()->connset->load();
0090     }
0091     return *KexiInternal::self()->connset;
0092 }
0093 
0094 KexiRecentProjects* Kexi::recentProjects()
0095 {
0096     return &KexiInternal::self()->recentProjects;
0097 }
0098 
0099 KDbDriverManager& Kexi::driverManager()
0100 {
0101     return KexiInternal::self()->driverManager;
0102 }
0103 
0104 KexiPart::Manager& Kexi::partManager()
0105 {
0106     return KexiInternal::self()->partManager;
0107 }
0108 
0109 void Kexi::deleteGlobalObjects()
0110 {
0111     KexiInternal::self()->destroy();
0112 }
0113 
0114 //temp
0115 
0116 bool _tempShowMacros = true;
0117 bool& Kexi::tempShowMacros()
0118 {
0119 #ifndef KEXI_MACROS_SUPPORT
0120     _tempShowMacros = false;
0121 #endif
0122     return _tempShowMacros;
0123 }
0124 
0125 bool _tempShowScripts = true;
0126 bool& Kexi::tempShowScripts()
0127 {
0128 #ifndef KEXI_SCRIPTS_SUPPORT
0129     _tempShowScripts = false;
0130 #endif
0131     return _tempShowScripts;
0132 }
0133 
0134 //--------------------------------------------------------------------------------
0135 QString Kexi::nameForViewMode(ViewMode mode, bool withAmpersand)
0136 {
0137     if (!withAmpersand)
0138         return Kexi::nameForViewMode(mode, true).remove('&');
0139 
0140     if (mode == NoViewMode)
0141         return xi18n("&No View");
0142     else if (mode == DataViewMode)
0143         return xi18n("&Data View");
0144     else if (mode == DesignViewMode)
0145         return xi18n("D&esign View");
0146     else if (mode == TextViewMode)
0147         return xi18n("&Text View");
0148 
0149     return xi18n("&Unknown");
0150 }
0151 
0152 //--------------------------------------------------------------------------------
0153 QString Kexi::iconNameForViewMode(ViewMode mode)
0154 {
0155     const char *const id =
0156         (mode == DataViewMode) ? KexiIconNameCStr("data-view") :
0157         (mode == DesignViewMode) ? KexiIconNameCStr("design-view") :
0158         (mode == TextViewMode) ? KexiIconNameCStr("sql-view"):
0159         0;
0160 
0161     return QLatin1String(id);
0162 }
0163 
0164 //--------------------------------------------------------------------------------
0165 
0166 ObjectStatus::ObjectStatus()
0167         : m_resultable(0), m_msgHandler(0)
0168 {
0169 }
0170 
0171 ObjectStatus::ObjectStatus(const QString& message, const QString& description)
0172         : m_resultable(0), m_msgHandler(0)
0173 {
0174     setStatus(message, description);
0175 }
0176 
0177 ObjectStatus::ObjectStatus(const KDbResultable* resultable, const QString& message, const QString& description)
0178         : m_resultable(0), m_msgHandler(0)
0179 {
0180     setStatus(resultable, message, description);
0181 }
0182 
0183 ObjectStatus::~ObjectStatus()
0184 {
0185     delete m_msgHandler;
0186 }
0187 
0188 const ObjectStatus& ObjectStatus::status() const
0189 {
0190     return *this;
0191 }
0192 
0193 bool ObjectStatus::error() const
0194 {
0195     return !message.isEmpty()
0196            || (m_resultable && m_resultable->result().isError());
0197 }
0198 
0199 void ObjectStatus::setStatus(const QString& message, const QString& description)
0200 {
0201     m_resultable = 0;
0202     this->message = message;
0203     this->description = description;
0204 }
0205 
0206 void ObjectStatus::setStatus(const KDbResultable* resultable, const QString& message, const QString& description)
0207 {
0208     m_resultable = resultable;
0209     this->message = message;
0210     this->description = description;
0211 }
0212 
0213 void ObjectStatus::setStatus(KDbResultInfo* resultInfo, const QString& message, const QString& description)
0214 {
0215     if (resultInfo) {
0216         if (message.isEmpty()) {
0217             this->message = resultInfo->message;
0218         } else {
0219             this->message = message + " " + resultInfo->message;
0220         }
0221 
0222         if (description.isEmpty()) {
0223             this->description = resultInfo->description;
0224         } else {
0225             this->description = description + " " + resultInfo->description;
0226         }
0227     } else {
0228         setStatus(message, description);
0229     }
0230 }
0231 
0232 void ObjectStatus::setStatus(const KDbResultable* resultable, KDbResultInfo* resultInfo,
0233                              const QString& message, const QString& description)
0234 {
0235     if (!resultable)
0236         setStatus(resultInfo, message, description);
0237     else if (!resultInfo)
0238         setStatus(resultable, message, description);
0239     else {
0240         setStatus(resultable, message, description);
0241         setStatus(resultInfo, this->message, this->description);
0242     }
0243 }
0244 
0245 void ObjectStatus::setStatus(const KDbResult &result, KDbResultInfo* resultInfo,
0246                              const QString& message, const QString& description)
0247 {
0248     //! @todo KEXI3 test this
0249     if (!result.isError()) {
0250         if (resultInfo) {
0251             setStatus(resultInfo, message, description);
0252         } else {
0253             setStatus(message, description);
0254         }
0255     }
0256     else {
0257         if (resultInfo) {
0258             KDbResult r = result;
0259             r.prependMessage(message);
0260             r.prependMessage(description);
0261             setStatus(resultInfo, r.messageTitle(), r.message());
0262         } else {
0263             setStatus(message, description);
0264         }
0265     }
0266 }
0267 
0268 void ObjectStatus::clearStatus()
0269 {
0270     message.clear();
0271     description.clear();
0272 }
0273 
0274 QString ObjectStatus::singleStatusString() const
0275 {
0276     if (message.isEmpty() || description.isEmpty())
0277         return message;
0278     return message + " " + description;
0279 }
0280 
0281 void ObjectStatus::append(const ObjectStatus& otherStatus)
0282 {
0283     if (message.isEmpty()) {
0284         message = otherStatus.message;
0285         description = otherStatus.description;
0286         return;
0287     }
0288     const QString s(otherStatus.singleStatusString());
0289     if (s.isEmpty())
0290         return;
0291     if (description.isEmpty()) {
0292         description = s;
0293         return;
0294     }
0295     description = description + " " + s;
0296 }
0297 
0298 //! @internal
0299 class ObjectStatusMessageHandler : public KDbMessageHandler
0300 {
0301 public:
0302     explicit ObjectStatusMessageHandler(ObjectStatus *status)
0303             : KDbMessageHandler()
0304             , m_status(status) {
0305     }
0306     virtual ~ObjectStatusMessageHandler() {
0307     }
0308 
0309     virtual void showErrorMessage(KDbMessageHandler::MessageType messageType,
0310                                   const QString &msg,
0311                                   const QString &details = QString(),
0312                                   const QString &caption = QString()) override
0313     {
0314         Q_UNUSED(messageType);
0315         Q_UNUSED(caption);
0316         m_status->setStatus(msg, details);
0317     }
0318 
0319     virtual void showErrorMessage(const KDbResult& result,
0320                                   KDbMessageHandler::MessageType messageType = KDbMessageHandler::Error,
0321                                   const QString& msg = QString(),
0322                                   const QString& caption = QString()) override
0323     {
0324         Q_UNUSED(messageType);
0325         m_status->setStatus(result, 0, caption, msg);
0326     }
0327 
0328     ObjectStatus *m_status;
0329 };
0330 
0331 ObjectStatus::operator KDbMessageHandler*()
0332 {
0333     if (!m_msgHandler)
0334         m_msgHandler = new ObjectStatusMessageHandler(this);
0335     return m_msgHandler;
0336 }
0337 
0338 void KEXI_UNFINISHED_INTERNAL(const QString& feature_name, const QString& extra_text,
0339                               QString* line1, QString* line2)
0340 {
0341     if (feature_name.isEmpty())
0342         *line1 = xi18n("This function is not available for version %1 of %2 application.",
0343                    QString(KEXI_VERSION_STRING), QString(KEXI_APP_NAME));
0344     else {
0345         QString feature_name_(feature_name);
0346         *line1 = xi18nc("@info",
0347                        "<resource>%1</resource> function is not available for version %2 of %3 application.",
0348                        feature_name_.remove('&'), QString(KEXI_VERSION_STRING), QString(KEXI_APP_NAME));
0349     }
0350 
0351     *line2 = extra_text;
0352 }
0353 
0354 void KEXI_UNFINISHED(const QString& feature_name, const QString& extra_text)
0355 {
0356     QString line1, line2;
0357     KEXI_UNFINISHED_INTERNAL(feature_name, extra_text, &line1, &line2);
0358     if (!line2.isEmpty())
0359         line2.prepend("\n");
0360     KMessageBox::sorry(0, line1 + line2);
0361 }
0362 
0363 QLabel *KEXI_UNFINISHED_LABEL(const QString& feature_name, const QString& extra_text)
0364 {
0365     QString line1, line2;
0366     KEXI_UNFINISHED_INTERNAL(feature_name, extra_text, &line1, &line2);
0367     QLabel *label = new QLabel(QLatin1String("<b>") + line1 + QLatin1String("</b><br>")
0368         + line2);
0369     label->setAlignment(Qt::AlignCenter);
0370     label->setWordWrap(true);
0371     label->setAutoFillBackground(true);
0372     label->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Preferred);
0373     return label;
0374 }
0375 
0376 //--------------------------------------------------------------------------------
0377 
0378 QString Kexi::defaultFileBasedDriverIconName()
0379 {
0380     return KexiIconName("file-database");
0381 }
0382 
0383 QIcon Kexi::defaultFileBasedDriverIcon()
0384 {
0385     return QIcon::fromTheme(defaultFileBasedDriverIconName());
0386 }
0387 
0388 QString Kexi::serverIconName()
0389 {
0390     return KexiIconName("network-server-database");
0391 }
0392 
0393 QIcon Kexi::serverIcon()
0394 {
0395     return QIcon::fromTheme(serverIconName());
0396 }
0397 
0398 QString Kexi::appIncorrectlyInstalledMessage()
0399 {
0400     return xi18nc("@info", "<application>%1</application> could have been incorrectly "
0401                            "installed or started. The application will be closed.",
0402                            QApplication::applicationDisplayName());
0403 }
0404 
0405 QString Kexi::basePathForProject(const KDbConnectionData& connectionData)
0406 {
0407     KDbDriverManager manager;
0408     const KDbDriverMetaData* driverMetaData = manager.driverMetaData(connectionData.driverId());
0409     if (driverMetaData && driverMetaData->isFileBased()) {
0410         const QFileInfo fileinfo(connectionData.databaseName());
0411         return fileinfo.path();
0412     }
0413     return QString();
0414 }
0415 
0416 bool Kexi::isKexiInstance()
0417 {
0418     return KAboutData::applicationData().componentName() == QLatin1String("kexi");
0419 }