File indexing completed on 2024-06-16 03:42:36
0001 /* 0002 File : String2DateTimeFilter.cpp 0003 Project : LabPlot 0004 Description : Conversion filter QString -> QDateTime. 0005 -------------------------------------------------------------------- 0006 SPDX-FileCopyrightText: 2007 Tilman Benkert <thzs@gmx.net> 0007 SPDX-FileCopyrightText: 2007 Knut Franke <knut.franke@gmx.de> 0008 SPDX-FileCopyrightText: 2017 Stefan Gerlach <stefan.gerlach@uni.kn> 0009 SPDX-License-Identifier: GPL-2.0-or-later 0010 */ 0011 0012 #include "String2DateTimeFilter.h" 0013 #include "backend/lib/XmlStreamReader.h" 0014 #include <QDate> 0015 #include <QDateTime> 0016 #include <QStringList> 0017 #include <QTime> 0018 #include <QUndoCommand> 0019 0020 #include <KLocalizedString> 0021 0022 class String2DateTimeFilterSetFormatCmd : public QUndoCommand { 0023 public: 0024 String2DateTimeFilterSetFormatCmd(String2DateTimeFilter* target, const QString& new_format); 0025 0026 void redo() override; 0027 void undo() override; 0028 0029 private: 0030 String2DateTimeFilter* m_target; 0031 QString m_other_format; 0032 }; 0033 0034 AbstractColumn::ColumnMode String2DateTimeFilter::columnMode() const { 0035 return AbstractColumn::ColumnMode::DateTime; 0036 } 0037 0038 QDateTime String2DateTimeFilter::dateTimeAt(int row) const { 0039 if (!m_inputs.value(0)) 0040 return {}; 0041 QString input_value = m_inputs.value(0)->textAt(row); 0042 if (input_value.isEmpty()) 0043 return {}; 0044 0045 // first try the selected format string m_format 0046 QDateTime result = QDateTime::fromString(input_value, m_format); 0047 result.setTimeSpec(Qt::UTC); 0048 if (result.isValid()) 0049 return result; 0050 0051 // fallback: 0052 // try other format strings built from date_formats and time_formats 0053 // comma and space are valid separators between date and time 0054 #if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)) 0055 QStringList strings = input_value.simplified().split(QLatin1Char(','), Qt::SkipEmptyParts); 0056 if (strings.size() == 1) 0057 strings = strings.at(0).split(QLatin1Char(' '), Qt::SkipEmptyParts); 0058 #else 0059 QStringList strings = input_value.simplified().split(QLatin1Char(','), QString::SkipEmptyParts); 0060 if (strings.size() == 1) 0061 strings = strings.at(0).split(QLatin1Char(' '), QString::SkipEmptyParts); 0062 #endif 0063 0064 if (strings.size() < 1) 0065 return result; // invalid date/time from first attempt 0066 0067 QDate date_result; 0068 QTime time_result; 0069 0070 QString date_string = strings.at(0).trimmed(); 0071 QString time_string; 0072 if (strings.size() > 1) 0073 time_string = strings.at(1).trimmed(); 0074 else 0075 time_string = date_string; 0076 0077 // try to find a valid date 0078 for (const auto& format : AbstractColumn::dateFormats()) { 0079 date_result = QDate::fromString(date_string, format); 0080 if (date_result.isValid()) 0081 break; 0082 } 0083 // try to find a valid time 0084 for (const auto& format : AbstractColumn::timeFormats()) { 0085 time_result = QTime::fromString(time_string, format); 0086 if (time_result.isValid()) 0087 break; 0088 } 0089 0090 if (!date_result.isValid() && time_result.isValid()) 0091 date_result.setDate(1900, 1, 1); // this is what QDateTime does e.g. for QDateTime::fromString("00:00","hh:mm"); 0092 else if (date_result.isValid() && !time_result.isValid()) 0093 time_result = QTime(0, 0, 0, 0); 0094 0095 return {date_result, time_result}; 0096 } 0097 0098 QDate String2DateTimeFilter::dateAt(int row) const { 0099 return dateTimeAt(row).date(); 0100 } 0101 0102 QTime String2DateTimeFilter::timeAt(int row) const { 0103 return dateTimeAt(row).time(); 0104 } 0105 0106 bool String2DateTimeFilter::inputAcceptable(int, const AbstractColumn* source) { 0107 return source->columnMode() == AbstractColumn::ColumnMode::Text; 0108 } 0109 0110 void String2DateTimeFilter::writeExtraAttributes(QXmlStreamWriter* writer) const { 0111 writer->writeAttribute(QStringLiteral("format"), format()); 0112 } 0113 0114 bool String2DateTimeFilter::load(XmlStreamReader* reader, bool preview) { 0115 if (preview) 0116 return true; 0117 0118 QXmlStreamAttributes attribs = reader->attributes(); 0119 QString str = attribs.value(reader->namespaceUri().toString(), QStringLiteral("format")).toString(); 0120 0121 if (AbstractSimpleFilter::load(reader, preview)) 0122 setFormat(str); 0123 else 0124 return false; 0125 0126 return !reader->hasError(); 0127 } 0128 0129 void String2DateTimeFilter::setFormat(const QString& format) { 0130 exec(new String2DateTimeFilterSetFormatCmd(this, format)); 0131 } 0132 0133 String2DateTimeFilterSetFormatCmd::String2DateTimeFilterSetFormatCmd(String2DateTimeFilter* target, const QString& new_format) 0134 : m_target(target) 0135 , m_other_format(new_format) { 0136 if (m_target->parentAspect()) 0137 setText(i18n("%1: set date-time format to %2", m_target->parentAspect()->name(), new_format)); 0138 else 0139 setText(i18n("set date-time format to %1", new_format)); 0140 } 0141 0142 void String2DateTimeFilterSetFormatCmd::redo() { 0143 QString tmp = m_target->m_format; 0144 m_target->m_format = m_other_format; 0145 m_other_format = tmp; 0146 Q_EMIT m_target->formatChanged(); 0147 } 0148 0149 void String2DateTimeFilterSetFormatCmd::undo() { 0150 redo(); 0151 }