File indexing completed on 2024-05-12 15:27:00
0001 /*************************************************************************** 0002 File : IntervalAttribute.h 0003 Project : LabPlot 0004 -------------------------------------------------------------------- 0005 0006 Copyright : (C) 2007 by Knut Franke (knut.franke@gmx.de) 0007 Copyright : (C) 2007 by Tilman Benkert (thzs@gmx.net) 0008 Description : A class representing an interval-based attribute 0009 0010 ***************************************************************************/ 0011 0012 /*************************************************************************** 0013 * * 0014 * This program is free software; you can redistribute it and/or modify * 0015 * it under the terms of the GNU General Public License as published by * 0016 * the Free Software Foundation; either version 2 of the License, or * 0017 * (at your option) any later version. * 0018 * * 0019 * This program is distributed in the hope that it will be useful, * 0020 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 0021 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 0022 * GNU General Public License for more details. * 0023 * * 0024 * You should have received a copy of the GNU General Public License * 0025 * along with m_intervals program; if not, write to the Free Software * 0026 * Foundation, Inc., 51 Franklin Street, Fifth Floor, * 0027 * Boston, MA 02110-1301 USA * 0028 * * 0029 ***************************************************************************/ 0030 0031 #ifndef INTERVALATTRIBUTE_H 0032 #define INTERVALATTRIBUTE_H 0033 0034 #include "Interval.h" 0035 #include <QVector> 0036 0037 //! A class representing an interval-based attribute 0038 template<class T> class IntervalAttribute { 0039 public: 0040 void setValue(const Interval<int>& i, T value) { 0041 // first: subtract the new interval from all others 0042 QVector< Interval<int> > temp_list; 0043 for (int c = 0; c < m_intervals.size(); c++) { 0044 temp_list = Interval<int>::subtract(m_intervals.at(c), i); 0045 if (temp_list.isEmpty()) { 0046 m_intervals.removeAt(c); 0047 m_values.removeAt(c--); 0048 } else { 0049 m_intervals.replace(c, temp_list.at(0)); 0050 if (temp_list.size() > 1) { 0051 m_intervals.insert(c, temp_list.at(1)); 0052 m_values.insert(c, m_values.at(c)); 0053 } 0054 } 0055 } 0056 0057 // second: try to merge the new interval with an old one 0058 for (int c = 0; c < m_intervals.size(); c++) { 0059 if (m_intervals.at(c).touches(i) && m_values.at(c) == value) { 0060 m_intervals.replace(c, Interval<int>::merge(m_intervals.at(c), i)); 0061 return; 0062 } 0063 } 0064 // if it could not be merged, just append it 0065 m_intervals.append(i); 0066 m_values.append(value); 0067 } 0068 0069 // overloaded for convenience 0070 void setValue(int row, T value) 0071 { 0072 setValue(Interval<int>(row, row), value); 0073 } 0074 0075 T value(int row) const 0076 { 0077 for(int c=m_intervals.size()-1; c>=0; c--) 0078 { 0079 if(m_intervals.at(c).contains(row)) 0080 return m_values.at(c); 0081 } 0082 return T(); 0083 } 0084 0085 void insertRows(int before, int count) 0086 { 0087 QVector< Interval<int> > temp_list; 0088 // first: split all intervals that contain 'before' 0089 for(int c=0; c<m_intervals.size(); c++) 0090 { 0091 if(m_intervals.at(c).contains(before)) 0092 { 0093 temp_list = Interval<int>::split(m_intervals.at(c), before); 0094 m_intervals.replace(c, temp_list.at(0)); 0095 if(temp_list.size()>1) 0096 { 0097 m_intervals.insert(c, temp_list.at(1)); 0098 m_values.insert(c, m_values.at(c)); 0099 c++; 0100 } 0101 0102 } 0103 } 0104 // second: translate all intervals that start at 'before' or later 0105 for(int c=0; c<m_intervals.size(); c++) 0106 { 0107 if(m_intervals.at(c).start() >= before) 0108 m_intervals[c].translate(count); 0109 } 0110 0111 } 0112 0113 void removeRows(int first, int count) 0114 { 0115 QVector< Interval<int> > temp_list; 0116 Interval<int> i(first, first+count-1); 0117 // first: remove the relevant rows from all intervals 0118 for(int c=0; c<m_intervals.size(); c++) 0119 { 0120 temp_list = Interval<int>::subtract(m_intervals.at(c), i); 0121 if(temp_list.isEmpty()) 0122 { 0123 m_intervals.removeAt(c); 0124 m_values.removeAt(c--); 0125 } 0126 else 0127 { 0128 m_intervals.replace(c, temp_list.at(0)); 0129 if(temp_list.size()>1) 0130 { 0131 m_intervals.insert(c, temp_list.at(1)); 0132 m_values.insert(c, m_values.at(c)); 0133 c++; 0134 } 0135 } 0136 } 0137 // second: translate all intervals that start at 'first+count' or later 0138 for(int c=0; c<m_intervals.size(); c++) 0139 { 0140 if(m_intervals.at(c).start() >= first+count) 0141 m_intervals[c].translate(-count); 0142 } 0143 // third: merge as many intervals as possible 0144 QVector<T> values_copy = m_values; 0145 QVector< Interval<int> > intervals_copy = m_intervals; 0146 m_values.clear(); 0147 m_intervals.clear(); 0148 for(int c=0; c<intervals_copy.size(); c++) 0149 { 0150 i = intervals_copy.at(c); 0151 T value = values_copy.at(c); 0152 for(int cc=0; cc<m_intervals.size(); cc++) 0153 { 0154 if( m_intervals.at(cc).touches(i) && 0155 m_values.at(cc) == value ) 0156 { 0157 m_intervals.replace(cc, Interval<int>::merge(m_intervals.at(cc),i)); 0158 return; 0159 } 0160 } 0161 // if it could not be merged, just append it 0162 m_intervals.append(i); 0163 m_values.append(value); 0164 } 0165 } 0166 0167 void clear() { m_values.clear(); m_intervals.clear(); } 0168 0169 QVector< Interval<int> > intervals() const { return m_intervals; } 0170 QVector<T> values() const { return m_values; } 0171 0172 private: 0173 QVector<T> m_values; 0174 QVector< Interval<int> > m_intervals; 0175 }; 0176 0177 //! A class representing an interval-based attribute (bool version) 0178 template<> class IntervalAttribute<bool> 0179 { 0180 public: 0181 IntervalAttribute<bool>() {} 0182 IntervalAttribute<bool>(const QVector< Interval<int> >& intervals) : m_intervals(intervals) {} 0183 0184 void setValue(const Interval<int>& i, bool value=true) 0185 { 0186 if(value) 0187 { 0188 foreach(const Interval<int>& iv, m_intervals) 0189 if(iv.contains(i)) 0190 return; 0191 0192 Interval<int>::mergeIntervalIntoList(&m_intervals, i); 0193 } else { // unset 0194 Interval<int>::subtractIntervalFromList(&m_intervals, i); 0195 } 0196 } 0197 0198 void setValue(int row, bool value) 0199 { 0200 setValue(Interval<int>(row, row), value); 0201 } 0202 0203 bool isSet(int row) const 0204 { 0205 foreach(Interval<int> iv, m_intervals) 0206 if(iv.contains(row)) 0207 return true; 0208 return false; 0209 } 0210 0211 bool isSet(const Interval<int>& i) const 0212 { 0213 foreach(Interval<int> iv, m_intervals) 0214 if(iv.contains(i)) 0215 return true; 0216 return false; 0217 } 0218 0219 void insertRows(int before, int count) 0220 { 0221 QVector< Interval<int> > temp_list; 0222 int c; 0223 // first: split all intervals that contain 'before' 0224 for(c=0; c<m_intervals.size(); c++) 0225 { 0226 if(m_intervals.at(c).contains(before)) 0227 { 0228 temp_list = Interval<int>::split(m_intervals.at(c), before); 0229 m_intervals.replace(c, temp_list.at(0)); 0230 if(temp_list.size()>1) 0231 m_intervals.insert(c++, temp_list.at(1)); 0232 0233 } 0234 } 0235 // second: translate all intervals that start at 'before' or later 0236 for(c=0; c<m_intervals.size(); c++) 0237 { 0238 if(m_intervals.at(c).start() >= before) 0239 m_intervals[c].translate(count); 0240 } 0241 0242 } 0243 0244 void removeRows(int first, int count) 0245 { 0246 int c; 0247 // first: remove the relevant rows from all intervals 0248 Interval<int>::subtractIntervalFromList(&m_intervals, Interval<int>(first, first+count-1)); 0249 // second: translate all intervals that start at 'first+count' or later 0250 for(c=0; c<m_intervals.size(); c++) 0251 { 0252 if(m_intervals.at(c).start() >= first+count) 0253 m_intervals[c].translate(-count); 0254 } 0255 // third: merge as many intervals as possible 0256 for(c=m_intervals.size()-1; c>=0; c--) 0257 { 0258 Interval<int> iv = m_intervals.takeAt(c); 0259 int size_before = m_intervals.size(); 0260 Interval<int>::mergeIntervalIntoList(&m_intervals, iv); 0261 if(size_before == m_intervals.size()) // merge successful 0262 c--; 0263 } 0264 } 0265 0266 QVector< Interval<int> > intervals() const { return m_intervals; } 0267 0268 void clear() { m_intervals.clear(); } 0269 0270 private: 0271 QVector< Interval<int> > m_intervals; 0272 }; 0273 0274 #endif