Changeset View
Changeset View
Standalone View
Standalone View
kmymoney/plugins/csvimport/csvwizard.cpp
Show All 13 Lines | |||||
14 | * it under the terms of the GNU General Public License as published by * | 14 | * it under the terms of the GNU General Public License as published by * | ||
15 | * the Free Software Foundation; either version 2 of the License, or * | 15 | * the Free Software Foundation; either version 2 of the License, or * | ||
16 | * (at your option) any later version. * | 16 | * (at your option) any later version. * | ||
17 | * * | 17 | * * | ||
18 | ********************************************************************************/ | 18 | ********************************************************************************/ | ||
19 | 19 | | |||
20 | #include "csvwizard.h" | 20 | #include "csvwizard.h" | ||
21 | 21 | | |||
22 | #include <QWizard> | 22 | // ---------------------------------------------------------------------------- | ||
23 | #include <QWizardPage> | 23 | // QT Includes | ||
24 | | ||||
25 | #include <QDesktopWidget> | ||||
24 | #include <QCloseEvent> | 26 | #include <QCloseEvent> | ||
25 | #include <QTimer> | | |||
26 | #include <QDebug> | 27 | #include <QDebug> | ||
27 | #include <QDesktopWidget> | | |||
28 | #include <QTextCodec> | 28 | #include <QTextCodec> | ||
29 | #include <QAbstractButton> | ||||
30 | | ||||
31 | // ---------------------------------------------------------------------------- | ||||
32 | // KDE Includes | ||||
29 | 33 | | |||
30 | #include <KMessageBox> | 34 | #include <KMessageBox> | ||
31 | #include <KLocalizedString> | 35 | #include <KLocalizedString> | ||
32 | #include <KConfigGroup> | 36 | #include <KConfigGroup> | ||
33 | #include <KColorScheme> | 37 | #include <KColorScheme> | ||
34 | #include <kjobwidgets.h> | | |||
35 | #include <kio/job.h> | | |||
36 | 38 | | |||
37 | #include "convdate.h" | 39 | // ---------------------------------------------------------------------------- | ||
38 | #include "csvutil.h" | 40 | // Project Includes | ||
39 | | ||||
40 | #include "mymoneyfile.h" | | |||
41 | 41 | | |||
42 | #include "ui_csvwizard.h" | 42 | #include "ui_csvwizard.h" | ||
43 | #include "ui_introwizardpage.h" | 43 | #include "ui_introwizardpage.h" | ||
44 | #include "ui_separatorwizardpage.h" | 44 | #include "ui_separatorwizardpage.h" | ||
45 | #include "ui_rowswizardpage.h" | 45 | #include "ui_rowswizardpage.h" | ||
46 | #include "ui_bankingwizardpage.h" | 46 | #include "ui_bankingwizardpage.h" | ||
47 | #include "ui_formatswizardpage.h" | | |||
48 | #include "ui_investmentwizardpage.h" | 47 | #include "ui_investmentwizardpage.h" | ||
49 | #include "ui_priceswizardpage.h" | 48 | #include "ui_priceswizardpage.h" | ||
49 | #include "ui_formatswizardpage.h" | ||||
50 | | ||||
51 | #include "ui_securitiesdlg.h" | ||||
52 | #include "ui_securitydlg.h" | ||||
50 | 53 | | |||
51 | CSVWizard::CSVWizard() : | 54 | CSVWizard::CSVWizard(CsvImporterPlugin* plugin, CSVImporter* importer) : | ||
52 | ui(new Ui::CSVWizard), | 55 | ui(new Ui::CSVWizard), | ||
53 | m_pageIntro(0), | 56 | m_plugin(plugin), | ||
54 | m_pageSeparator(0), | 57 | m_imp(importer), | ||
55 | m_pageBanking(0), | 58 | m_wiz(new QWizard) | ||
56 | m_pageInvestment(0) | | |||
57 | { | 59 | { | ||
58 | ui->setupUi(this); | 60 | ui->setupUi(this); | ||
59 | 61 | ui->tableView->setModel(m_imp->m_file->m_model); | |||
60 | m_parse = new Parse; | 62 | readWindowSize(CSVImporter::configFile()); | ||
61 | m_convertDate = new ConvertDate; | 63 | m_wiz->setWizardStyle(QWizard::ClassicStyle); | ||
62 | m_csvUtil = new CsvUtil; | 64 | ui->horizontalLayout->addWidget(m_wiz); | ||
63 | | ||||
64 | st = MyMoneyStatement(); | | |||
65 | m_curId = -1; | 65 | m_curId = -1; | ||
66 | m_lastId = -1; | 66 | m_lastId = -1; | ||
67 | m_maxColumnCount = 0; | 67 | m_wiz->installEventFilter(this); // event filter for escape key presses | ||
68 | m_importError = false; | | |||
69 | m_fileEndLine = 0; | | |||
70 | ui->tableWidget->horizontalHeader()->setSectionResizeMode(QHeaderView::Interactive); | | |||
71 | | ||||
72 | m_wizard = new QWizard; | | |||
73 | m_wizard->setWizardStyle(QWizard::ClassicStyle); | | |||
74 | ui->horizontalLayout->addWidget(m_wizard); | | |||
75 | m_wizard->installEventFilter(this); // event filter for escape key presses | | |||
76 | 68 | | |||
77 | m_wizard->button(QWizard::BackButton)->setIcon(QIcon::fromTheme(QStringLiteral("go-previous"))); | 69 | m_wiz->button(QWizard::BackButton)->setIcon(QIcon::fromTheme(QStringLiteral("go-previous"))); | ||
78 | m_wizard->button(QWizard::CancelButton)->setIcon(QIcon::fromTheme(QStringLiteral("dialog-cancel"), | 70 | m_wiz->button(QWizard::CancelButton)->setIcon(QIcon::fromTheme(QStringLiteral("dialog-cancel"), | ||
79 | QIcon::fromTheme(QStringLiteral("stop")))); | 71 | QIcon::fromTheme(QStringLiteral("stop")))); | ||
80 | m_wizard->button(QWizard::CustomButton2)->setIcon(QIcon::fromTheme(QStringLiteral("kmymoney"))); | 72 | m_wiz->button(QWizard::CustomButton2)->setIcon(QIcon::fromTheme(QStringLiteral("kmymoney"))); | ||
81 | m_wizard->button(QWizard::FinishButton)->setIcon(QIcon::fromTheme(QStringLiteral("dialog-ok-apply"), | 73 | m_wiz->button(QWizard::FinishButton)->setIcon(QIcon::fromTheme(QStringLiteral("dialog-ok-apply"), | ||
82 | QIcon::fromTheme(QStringLiteral("finish")))); | 74 | QIcon::fromTheme(QStringLiteral("finish")))); | ||
83 | m_wizard->button(QWizard::CustomButton1)->setIcon(QIcon::fromTheme(QStringLiteral("system-file-manager"))); | 75 | m_wiz->button(QWizard::CustomButton1)->setIcon(QIcon::fromTheme(QStringLiteral("system-file-manager"))); | ||
84 | m_wizard->button(QWizard::CustomButton3)->setIcon(QIcon::fromTheme(QStringLiteral("invest-applet"))); | 76 | m_wiz->button(QWizard::CustomButton3)->setIcon(QIcon::fromTheme(QStringLiteral("invest-applet"))); | ||
85 | m_wizard->button(QWizard::NextButton)->setIcon(QIcon::fromTheme(QStringLiteral("go-next"))); | 77 | m_wiz->button(QWizard::NextButton)->setIcon(QIcon::fromTheme(QStringLiteral("go-next"))); | ||
86 | } | | |||
87 | 78 | | |||
88 | void CSVWizard::init() | 79 | m_pageIntro = new IntroPage(this, m_imp); | ||
89 | { | 80 | m_wiz->setPage(PageIntro, m_pageIntro); | ||
90 | m_pageIntro = new IntroPage; | | |||
91 | m_wizard->setPage(PageIntro, m_pageIntro); | | |||
92 | m_pageIntro->setParent(this); | | |||
93 | 81 | | |||
94 | m_pageSeparator = new SeparatorPage; | 82 | m_pageSeparator = new SeparatorPage(this, m_imp); | ||
95 | m_wizard->setPage(PageSeparator, m_pageSeparator); | 83 | m_wiz->setPage(PageSeparator, m_pageSeparator); | ||
96 | m_pageSeparator->setParent(this); | | |||
97 | 84 | | |||
98 | m_pageRows = new RowsPage; | 85 | m_pageRows = new RowsPage(this, m_imp); | ||
99 | m_wizard->setPage(PageRows, m_pageRows); | 86 | m_wiz->setPage(PageRows, m_pageRows); | ||
100 | m_pageRows->setParent(this); | | |||
101 | 87 | | |||
102 | m_pageFormats = new FormatsPage; | 88 | m_pageFormats = new FormatsPage(this, m_imp); | ||
103 | m_wizard->setPage(PageFormats, m_pageFormats); | 89 | m_wiz->setPage(PageFormats, m_pageFormats); | ||
104 | m_pageFormats->setParent(this); | 90 | | ||
91 | showStage(); | ||||
92 | m_wiz->button(QWizard::CustomButton1)->setEnabled(false); | ||||
105 | 93 | | |||
106 | m_stageLabels << ui->label_intro << ui->label_separators << ui->label_rows << ui->label_columns << ui->label_columns << ui->label_columns << ui->label_formats; | 94 | m_stageLabels << ui->label_intro << ui->label_separators << ui->label_rows << ui->label_columns << ui->label_columns << ui->label_columns << ui->label_formats; | ||
107 | m_pageFormats->setFinalPage(true); | 95 | m_pageFormats->setFinalPage(true); | ||
108 | 96 | | |||
109 | this->setAttribute(Qt::WA_DeleteOnClose, true); | 97 | this->setAttribute(Qt::WA_DeleteOnClose, true); | ||
110 | 98 | | |||
111 | m_profileList.clear(); | 99 | connect(m_wiz->button(QWizard::FinishButton), &QAbstractButton::clicked, this, &CSVWizard::slotClose); | ||
112 | findCodecs(); | 100 | connect(m_wiz->button(QWizard::CancelButton), &QAbstractButton::clicked, this, &QWidget::close); | ||
113 | m_config = KSharedConfig::openConfig(QStandardPaths::writableLocation(QStandardPaths::ConfigLocation) + | 101 | connect(m_wiz->button(QWizard::CustomButton1), &QAbstractButton::clicked, this, &CSVWizard::fileDialogClicked); | ||
114 | QDir::separator() + | 102 | connect(m_wiz->button(QWizard::CustomButton2), &QAbstractButton::clicked, this, &CSVWizard::importClicked); | ||
115 | "csvimporterrc"); | 103 | connect(m_wiz->button(QWizard::CustomButton3), &QAbstractButton::clicked, this, &CSVWizard::saveAsQIFClicked); | ||
116 | validateConfigFile(m_config); | 104 | connect(m_wiz, SIGNAL(currentIdChanged(int)), this, SLOT(slotIdChanged(int))); | ||
117 | readMiscSettings(m_config); | | |||
118 | | ||||
119 | connect(m_pageFormats, SIGNAL(statementReady(MyMoneyStatement&)), m_plugin, SLOT(slotGetStatement(MyMoneyStatement&))); | | |||
120 | | ||||
121 | connect(m_wizard->button(QWizard::FinishButton), SIGNAL(clicked()), this, SLOT(slotClose())); | | |||
122 | connect(m_wizard->button(QWizard::CancelButton), SIGNAL(clicked()), this, SLOT(close())); | | |||
123 | connect(m_wizard->button(QWizard::CustomButton1), SIGNAL(clicked()), this, SLOT(slotFileDialogClicked())); | | |||
124 | connect(m_wizard->button(QWizard::CustomButton2), SIGNAL(clicked()), m_pageFormats, SLOT(slotImportClicked())); | | |||
125 | connect(m_wizard->button(QWizard::CustomButton3), SIGNAL(clicked()), m_pageFormats, SLOT(slotSaveAsQIFClicked())); | | |||
126 | connect(m_wizard, SIGNAL(currentIdChanged(int)), this, SLOT(slotIdChanged(int))); | | |||
127 | 105 | | |||
128 | ui->tableWidget->setWordWrap(false); | 106 | ui->tableView->setWordWrap(false); | ||
129 | 107 | | |||
130 | m_vScrollBar = ui->tableWidget->verticalScrollBar(); | 108 | m_vScrollBar = ui->tableView->verticalScrollBar(); | ||
131 | m_vScrollBar->setTracking(false); | 109 | m_vScrollBar->setTracking(false); | ||
132 | m_dateFormats << "yyyy/MM/dd" << "MM/dd/yyyy" << "dd/MM/yyyy"; | | |||
133 | 110 | | |||
134 | m_clearBrush = KColorScheme(QPalette::Normal).background(KColorScheme::NormalBackground); | 111 | m_clearBrush = KColorScheme(QPalette::Normal).background(KColorScheme::NormalBackground); | ||
135 | m_clearBrushText = KColorScheme(QPalette::Normal).foreground(KColorScheme::NormalText); | 112 | m_clearBrushText = KColorScheme(QPalette::Normal).foreground(KColorScheme::NormalText); | ||
136 | m_colorBrush = KColorScheme(QPalette::Normal).background(KColorScheme::PositiveBackground); | 113 | m_colorBrush = KColorScheme(QPalette::Normal).background(KColorScheme::PositiveBackground); | ||
137 | m_colorBrushText = KColorScheme(QPalette::Normal).foreground(KColorScheme::PositiveText); | 114 | m_colorBrushText = KColorScheme(QPalette::Normal).foreground(KColorScheme::PositiveText); | ||
138 | m_errorBrush = KColorScheme(QPalette::Normal).background(KColorScheme::NegativeBackground); | 115 | m_errorBrush = KColorScheme(QPalette::Normal).background(KColorScheme::NegativeBackground); | ||
139 | m_errorBrushText = KColorScheme(QPalette::Normal).foreground(KColorScheme::NegativeText); | 116 | m_errorBrushText = KColorScheme(QPalette::Normal).foreground(KColorScheme::NegativeText); | ||
140 | 117 | | |||
141 | int y = (QApplication::desktop()->height() - this->height()) / 2; | | |||
142 | int x = (QApplication::desktop()->width() - this->width()) / 2; | | |||
143 | move(x, y); | | |||
144 | show(); | 118 | show(); | ||
145 | } | 119 | } | ||
146 | 120 | | |||
147 | CSVWizard::~CSVWizard() | 121 | CSVWizard::~CSVWizard() | ||
148 | { | 122 | { | ||
149 | delete ui; | 123 | delete ui; | ||
150 | delete m_parse; | 124 | if (m_wiz) | ||
151 | delete m_convertDate; | 125 | delete m_wiz; | ||
152 | delete m_csvUtil; | | |||
153 | delete m_wizard; | | |||
154 | } | 126 | } | ||
155 | 127 | | |||
156 | void CSVWizard::showStage() | 128 | void CSVWizard::showStage() | ||
157 | { | 129 | { | ||
158 | QString str = ui->label_intro->text(); | 130 | QString str = ui->label_intro->text(); | ||
159 | ui->label_intro->setText("<b>" + str + "</b>"); | 131 | ui->label_intro->setText(QLatin1String("<b>") + str + QLatin1String("/<b>")); | ||
160 | } | 132 | } | ||
161 | 133 | | |||
162 | void CSVWizard::readMiscSettings(const KSharedConfigPtr& config) { | 134 | void CSVWizard::readWindowSize(const KSharedConfigPtr& config) { | ||
163 | KConfigGroup miscGroup(config, "Misc"); | 135 | KConfigGroup miscGroup(config, CSVImporter::m_confMiscName); | ||
164 | m_initialWidth = miscGroup.readEntry("Width", 800); | 136 | m_initialWidth = miscGroup.readEntry(CSVImporter::m_miscSettingsConfName.value(ConfWidth), 800); | ||
165 | m_initialHeight = miscGroup.readEntry("Height", 400); | 137 | m_initialHeight = miscGroup.readEntry(CSVImporter::m_miscSettingsConfName.value(ConfHeight), 400); | ||
166 | m_autodetect.clear(); | | |||
167 | m_autodetect.insert(CSVWizard::AutoFieldDelimiter, miscGroup.readEntry("AutoFieldDelimiter", true)); | | |||
168 | m_autodetect.insert(CSVWizard::AutoDecimalSymbol, miscGroup.readEntry("AutoDecimalSymbol", true)); | | |||
169 | m_autodetect.insert(CSVWizard::AutoDateFormat, miscGroup.readEntry("AutoDateFormat", true)); | | |||
170 | m_autodetect.insert(CSVWizard::AutoAccountInvest, miscGroup.readEntry("AutoAccountInvest", true)); | | |||
171 | m_autodetect.insert(CSVWizard::AutoAccountBank, miscGroup.readEntry("AutoAccountBank", true)); | | |||
172 | } | 138 | } | ||
173 | 139 | | |||
174 | void CSVWizard::saveWindowSize(const KSharedConfigPtr& config) { | 140 | void CSVWizard::saveWindowSize(const KSharedConfigPtr& config) { | ||
175 | KConfigGroup miscGroup(config, "Misc"); | 141 | KConfigGroup miscGroup(config, CSVImporter::m_confMiscName); | ||
176 | m_initialHeight = this->geometry().height(); | 142 | m_initialHeight = this->geometry().height(); | ||
177 | m_initialWidth = this->geometry().width(); | 143 | m_initialWidth = this->geometry().width(); | ||
178 | miscGroup.writeEntry("Width", m_initialWidth); | 144 | miscGroup.writeEntry(CSVImporter::m_miscSettingsConfName.value(ConfWidth), m_initialWidth); | ||
179 | miscGroup.writeEntry("Height", m_initialHeight); | 145 | miscGroup.writeEntry(CSVImporter::m_miscSettingsConfName.value(ConfHeight), m_initialHeight); | ||
180 | miscGroup.sync(); | | |||
181 | } | | |||
182 | | ||||
183 | bool CSVWizard::updateConfigFile(const KSharedConfigPtr& config, const QList<int>& kmmVer) | | |||
184 | { | | |||
185 | QString configFilePath = config.constData()->name(); | | |||
186 | QFile::copy(configFilePath, configFilePath + ".bak"); | | |||
187 | | ||||
188 | KConfigGroup profileNamesGroup(config, "ProfileNames"); | | |||
189 | QStringList bankProfiles = profileNamesGroup.readEntry("Bank", QStringList()); | | |||
190 | QStringList investProfiles = profileNamesGroup.readEntry("Invest", QStringList()); | | |||
191 | QStringList invalidBankProfiles = profileNamesGroup.readEntry("InvalidBank", QStringList()); // get profiles that was marked invalid during last update | | |||
192 | QStringList invalidInvestProfiles = profileNamesGroup.readEntry("InvalidInvest", QStringList()); | | |||
193 | QString bankPrefix = "Bank-"; | | |||
194 | QString investPrefix = "Invest-"; | | |||
195 | | ||||
196 | uint version = kmmVer[0]*100 + kmmVer[1]*10 + kmmVer[2]; | | |||
197 | | ||||
198 | // for kmm < 5.0.0 change 'BankNames' to 'ProfileNames' and remove 'MainWindow' group | | |||
199 | if (version < 500 && bankProfiles.isEmpty()) { | | |||
200 | KConfigGroup oldProfileNamesGroup(config, "BankProfiles"); | | |||
201 | bankProfiles = oldProfileNamesGroup.readEntry("BankNames", QStringList()); // profile names are under 'BankNames' entry for kmm < 5.0.0 | | |||
202 | bankPrefix = "Profiles-"; // needed to remove non-existent profiles in first run | | |||
203 | oldProfileNamesGroup.deleteGroup(); | | |||
204 | KConfigGroup oldMainWindowGroup(config, "MainWindow"); | | |||
205 | oldMainWindowGroup.deleteGroup(); | | |||
206 | } | | |||
207 | | ||||
208 | bool firstTry = false; | | |||
209 | if (invalidBankProfiles.isEmpty() && invalidInvestProfiles.isEmpty()) // if there is no invalid profiles then this might be first update try | | |||
210 | firstTry = true; | | |||
211 | | ||||
212 | bool ret = true; | | |||
213 | int invalidProfileResponse = QMessageBox::No; | | |||
214 | | ||||
215 | for (QStringList::Iterator profileName = bankProfiles.begin(); profileName != bankProfiles.end(); ++profileName) { | | |||
216 | | ||||
217 | KConfigGroup bankProfile(config, bankPrefix + *profileName); | | |||
218 | if (!bankProfile.exists() && !invalidBankProfiles.contains(*profileName)) { // if there is reference to profile but no profile then remove this reference | | |||
219 | profileName = bankProfiles.erase(profileName); | | |||
220 | profileName--; | | |||
221 | continue; | | |||
222 | } | | |||
223 | | ||||
224 | // for kmm < 5.0.0 remove 'FileType' and 'ProfileName' and assign them to either "Bank=" or "Invest=" | | |||
225 | if (version < 500) { | | |||
226 | KConfigGroup oldBankProfile(config, "Profiles-" + *profileName); // if half of configuration is updated and the other one untouched this is needed | | |||
227 | QString oldProfileType = oldBankProfile.readEntry("FileType", QString()); | | |||
228 | KConfigGroup newProfile; | | |||
229 | if (oldProfileType == "Invest") { | | |||
230 | newProfile = KConfigGroup(config, "Invest-" + *profileName); | | |||
231 | investProfiles.append(*profileName); | | |||
232 | profileName = bankProfiles.erase(profileName); | | |||
233 | profileName--; | | |||
234 | } | | |||
235 | else if (oldProfileType == "Banking") | | |||
236 | newProfile = KConfigGroup(config, "Bank-" + *profileName); | | |||
237 | else { | | |||
238 | if (invalidProfileResponse != QMessageBox::YesToAll && invalidProfileResponse != QMessageBox::NoToAll) { | | |||
239 | if (!firstTry && | | |||
240 | !invalidBankProfiles.contains(*profileName)) // if it isn't first update run and profile isn't on the list of invalid ones then don't bother | | |||
241 | continue; | | |||
242 | invalidProfileResponse = QMessageBox::warning(m_wizard, i18n("CSV import"), | | |||
243 | i18n("<center>During update of <b>%1</b><br>" | | |||
244 | "the profile type for <b>%2</b> could not be recognized.<br>" | | |||
245 | "The profile cannot be used because of that.<br>" | | |||
246 | "Do you want to delete it?</center>", | | |||
247 | configFilePath, *profileName), | | |||
248 | QMessageBox::Yes | QMessageBox::YesToAll | | | |||
249 | QMessageBox::No | QMessageBox::NoToAll, QMessageBox::No ); | | |||
250 | } | | |||
251 | | ||||
252 | switch (invalidProfileResponse) { | | |||
253 | case QMessageBox::YesToAll: | | |||
254 | case QMessageBox::Yes: | | |||
255 | oldBankProfile.deleteGroup(); | | |||
256 | invalidBankProfiles.removeOne(*profileName); | | |||
257 | profileName = bankProfiles.erase(profileName); | | |||
258 | --profileName; | | |||
259 | break; | | |||
260 | case QMessageBox::NoToAll: | | |||
261 | case QMessageBox::No: | | |||
262 | if (!invalidBankProfiles.contains(*profileName)) // on user request: don't delete profile but keep eye on it | | |||
263 | invalidBankProfiles.append(*profileName); | | |||
264 | ret = false; | | |||
265 | break; | | |||
266 | } | | |||
267 | continue; | | |||
268 | } | | |||
269 | oldBankProfile.deleteEntry("FileType"); | | |||
270 | oldBankProfile.deleteEntry("ProfileName"); | | |||
271 | oldBankProfile.deleteEntry("DebitFlag"); | | |||
272 | oldBankProfile.deleteEntry("InvDirectory"); | | |||
273 | oldBankProfile.deleteEntry("CsvDirectory"); | | |||
274 | oldBankProfile.copyTo(&newProfile); | | |||
275 | oldBankProfile.deleteGroup(); | | |||
276 | newProfile.sync(); | | |||
277 | oldBankProfile.sync(); | | |||
278 | } | | |||
279 | } | | |||
280 | | ||||
281 | for (QStringList::Iterator profileName = investProfiles.begin(); profileName != investProfiles.end(); ++profileName) { | | |||
282 | | ||||
283 | KConfigGroup investProfile(config, investPrefix + *profileName); | | |||
284 | if (!investProfile.exists() && !invalidInvestProfiles.contains(*profileName)) { // if there is reference to profile but no profile then remove this reference | | |||
285 | investProfiles.erase(profileName); | | |||
286 | continue; | | |||
287 | } | | |||
288 | } | | |||
289 | | ||||
290 | profileNamesGroup.writeEntry("Bank", bankProfiles); // update profile names as some of them might have been changed | | |||
291 | profileNamesGroup.writeEntry("Invest", investProfiles); | | |||
292 | | ||||
293 | if (invalidBankProfiles.isEmpty()) // if no invalid profiles then we don't need this variable anymore | | |||
294 | profileNamesGroup.deleteEntry("InvalidBank"); | | |||
295 | else | | |||
296 | profileNamesGroup.writeEntry("InvalidBank", invalidBankProfiles); | | |||
297 | | ||||
298 | if (invalidInvestProfiles.isEmpty()) | | |||
299 | profileNamesGroup.deleteEntry("InvalidInvest"); | | |||
300 | else | | |||
301 | profileNamesGroup.writeEntry("InvalidInvest", invalidInvestProfiles); | | |||
302 | | ||||
303 | if (ret) | | |||
304 | QFile::remove(configFilePath + ".bak"); // remove backup if all is ok | | |||
305 | | ||||
306 | return ret; | | |||
307 | } | | |||
308 | | ||||
309 | void CSVWizard::validateConfigFile(const KSharedConfigPtr& config) | | |||
310 | { | | |||
311 | KConfigGroup profileNamesGroup(config, "ProfileNames"); | | |||
312 | if (!profileNamesGroup.exists()) { | | |||
313 | profileNamesGroup.writeEntry("Bank", QStringList()); | | |||
314 | profileNamesGroup.writeEntry("Invest", QStringList()); | | |||
315 | profileNamesGroup.writeEntry("SPrices", QStringList()); | | |||
316 | profileNamesGroup.writeEntry("PriorBank", int()); | | |||
317 | profileNamesGroup.writeEntry("PriorInvest", int()); | | |||
318 | profileNamesGroup.writeEntry("PriorSPrices", int()); | | |||
319 | profileNamesGroup.sync(); | | |||
320 | } | | |||
321 | | ||||
322 | KConfigGroup miscGroup(config, "Misc"); | | |||
323 | if (!miscGroup.exists()) { | | |||
324 | miscGroup.writeEntry("Height", "400"); | | |||
325 | miscGroup.writeEntry("Width", "800"); | | |||
326 | miscGroup.sync(); | 146 | miscGroup.sync(); | ||
327 | } | 147 | } | ||
328 | 148 | | |||
329 | QList<int> kmmVer = miscGroup.readEntry("KMMVer", QList<int> {0, 0, 0}); | | |||
330 | QList<int> curKmmVer = QList<int> {5, 0, 0}; | | |||
331 | if (curKmmVer != kmmVer) { | | |||
332 | if (updateConfigFile(config, kmmVer)) // write kmmVer only if there were no errors | | |||
333 | miscGroup.writeEntry("KMMVer", curKmmVer); | | |||
334 | } | | |||
335 | | ||||
336 | KConfigGroup securitiesGroup(config, "Securities"); | | |||
337 | if (!securitiesGroup.exists()) { | | |||
338 | securitiesGroup.writeEntry("SecurityNameList", QStringList()); | | |||
339 | securitiesGroup.sync(); | | |||
340 | } | | |||
341 | } | | |||
342 | | ||||
343 | void CSVWizard::setCodecList(const QList<QTextCodec *> &list, QComboBox* comboBoxEncode) | | |||
344 | { | | |||
345 | comboBoxEncode->clear(); | | |||
346 | foreach (QTextCodec * codec, list) | | |||
347 | comboBoxEncode->addItem(codec->name(), codec->mibEnum()); | | |||
348 | } | | |||
349 | | ||||
350 | void CSVWizard::findCodecs() | | |||
351 | { | | |||
352 | QMap<QString, QTextCodec *> codecMap; | | |||
353 | QRegExp iso8859RegExp("ISO[- ]8859-([0-9]+).*"); | | |||
354 | | ||||
355 | foreach (int mib, QTextCodec::availableMibs()) { | | |||
356 | QTextCodec *codec = QTextCodec::codecForMib(mib); | | |||
357 | | ||||
358 | QString sortKey = codec->name().toUpper(); | | |||
359 | int rank; | | |||
360 | | ||||
361 | if (sortKey.startsWith("UTF-8")) { // krazy:exclude=strings | | |||
362 | rank = 1; | | |||
363 | } else if (sortKey.startsWith("UTF-16")) { // krazy:exclude=strings | | |||
364 | rank = 2; | | |||
365 | } else if (iso8859RegExp.exactMatch(sortKey)) { | | |||
366 | if (iso8859RegExp.cap(1).size() == 1) | | |||
367 | rank = 3; | | |||
368 | else | | |||
369 | rank = 4; | | |||
370 | } else { | | |||
371 | rank = 5; | | |||
372 | } | | |||
373 | sortKey.prepend(QChar('0' + rank)); | | |||
374 | | ||||
375 | codecMap.insert(sortKey, codec); | | |||
376 | } | | |||
377 | m_codecs = codecMap.values(); | | |||
378 | } | | |||
379 | | ||||
380 | void CSVWizard::slotIdChanged(int id) | 149 | void CSVWizard::slotIdChanged(int id) | ||
381 | { | 150 | { | ||
382 | QString txt; | 151 | QString txt; | ||
383 | m_lastId = m_curId; | 152 | m_lastId = m_curId; | ||
384 | m_curId = id; | 153 | m_curId = id; | ||
385 | if ((m_lastId == -1) || (m_curId == -1)) { | 154 | if ((m_lastId == -1) || (m_curId == -1)) { | ||
386 | return; | 155 | return; | ||
387 | } | 156 | } | ||
388 | txt = m_stageLabels[m_lastId]->text(); | 157 | txt = m_stageLabels[m_lastId]->text(); | ||
389 | txt.remove(QRegExp("[<b>/]")); | 158 | txt.remove(QRegularExpression(QStringLiteral("[<b>/]"))); | ||
390 | m_stageLabels[m_lastId]->setText(txt); | 159 | m_stageLabels[m_lastId]->setText(txt); | ||
391 | 160 | | |||
392 | txt = m_stageLabels[m_curId]->text(); | 161 | txt = m_stageLabels[m_curId]->text(); | ||
393 | txt = "<b>" + txt + "</b>"; | 162 | txt = QLatin1String("<b>") + txt + QLatin1String("</b>"); | ||
394 | m_stageLabels[m_curId]->setText(txt); | 163 | m_stageLabels[m_curId]->setText(txt); | ||
395 | } | 164 | } | ||
396 | 165 | | |||
397 | void CSVWizard::clearColumnsBackground(int col) { | 166 | void CSVWizard::clearColumnsBackground(const int col) | ||
167 | { | ||||
398 | QList<int> columnList; | 168 | QList<int> columnList; | ||
399 | columnList << col; | 169 | columnList << col; | ||
400 | clearColumnsBackground(columnList); | 170 | clearColumnsBackground(columnList); | ||
401 | } | 171 | } | ||
402 | 172 | | |||
403 | void CSVWizard::clearColumnsBackground(QList<int>& columnList) | 173 | void CSVWizard::clearColumnsBackground(const QList<int> &columnList) | ||
404 | { | 174 | { | ||
405 | for (int row = m_startLine -1 ; row < m_endLine; ++row) { | 175 | QStandardItemModel *model = m_imp->m_file->m_model; | ||
406 | for (QList<int>::const_iterator col = columnList.constBegin(); col < columnList.constEnd(); ++col) { | 176 | for (int i = m_imp->m_profile->m_startLine; i <= m_imp->m_profile->m_endLine; ++i) { | ||
407 | QTableWidgetItem* item = ui->tableWidget->item(row, *col); | 177 | foreach (const auto j, columnList) { | ||
408 | item->setBackground(m_clearBrush); | 178 | model->item(i, j)->setBackground(m_clearBrush); | ||
409 | item->setForeground(m_clearBrushText); | 179 | model->item(i, j)->setForeground(m_clearBrushText); | ||
410 | } | 180 | } | ||
411 | } | 181 | } | ||
412 | } | 182 | } | ||
413 | 183 | | |||
414 | void CSVWizard::clearBackground() | 184 | void CSVWizard::clearBackground() | ||
415 | { | 185 | { | ||
416 | for (int row = 0; row < ui->tableWidget->rowCount(); ++row) { | 186 | QStandardItemModel *model = m_imp->m_file->m_model; | ||
417 | for (int col = 0; col < ui->tableWidget->columnCount(); ++col) { | 187 | int rowCount = model->rowCount(); | ||
418 | QTableWidgetItem *item = ui->tableWidget->item(row, col); | 188 | int colCount = model->columnCount(); | ||
419 | item->setBackground(m_clearBrush); | 189 | for (int i = 0; i < rowCount; ++i) { | ||
420 | item->setForeground(m_clearBrushText); | 190 | for (int j = 0; j < colCount; ++j) { | ||
191 | model->item(i, j)->setBackground(m_clearBrush); | ||||
192 | model->item(i, j)->setForeground(m_clearBrushText); | ||||
421 | } | 193 | } | ||
422 | } | 194 | } | ||
423 | } | 195 | } | ||
424 | 196 | | |||
425 | void CSVWizard::markUnwantedRows() | 197 | void CSVWizard::markUnwantedRows() | ||
426 | { | 198 | { | ||
427 | int first = m_startLine - 1; | 199 | QStandardItemModel *model = m_imp->m_file->m_model; | ||
428 | int last = m_endLine - 1; | 200 | int rowCount = model->rowCount(); | ||
429 | // | 201 | int colCount = model->columnCount(); | ||
430 | // highlight unwanted lines instead of not showing them. | | |||
431 | // | | |||
432 | QBrush brush; | 202 | QBrush brush; | ||
433 | QBrush brushText; | 203 | QBrush brushText; | ||
434 | for (int row = 0; row < ui->tableWidget->rowCount(); row++) { | 204 | for (int i = 0; i < rowCount; ++i) { | ||
435 | if ((row < first) || (row > last)) { | 205 | if ((i < m_imp->m_profile->m_startLine) || (i > m_imp->m_profile->m_endLine)) { | ||
436 | brush = m_errorBrush; | 206 | brush = m_errorBrush; | ||
437 | brushText = m_errorBrushText; | 207 | brushText = m_errorBrushText; | ||
438 | } else { | 208 | } else { | ||
439 | brush = m_clearBrush; | 209 | brush = m_clearBrush; | ||
440 | brushText = m_clearBrushText; | 210 | brushText = m_clearBrushText; | ||
441 | } | 211 | } | ||
442 | for (int col = 0; col < ui->tableWidget->columnCount(); col ++) { | 212 | for (int j = 0; j < colCount; ++j) { | ||
443 | if (ui->tableWidget->item(row, col) != 0) { | 213 | model->item(i, j)->setBackground(brush); | ||
444 | ui->tableWidget->item(row, col)->setBackground(brush); | 214 | model->item(i, j)->setForeground(brushText); | ||
445 | ui->tableWidget->item(row, col)->setForeground(brushText); | | |||
446 | } | | |||
447 | } | 215 | } | ||
448 | } | 216 | } | ||
449 | } | 217 | } | ||
450 | 218 | | |||
451 | QList<MyMoneyAccount> CSVWizard::findAccounts(QList<MyMoneyAccount::accountTypeE> &accountTypes, QString& statementHeader) | 219 | void CSVWizard::updateWindowSize() | ||
452 | { | 220 | { | ||
453 | MyMoneyFile* file = MyMoneyFile::instance(); | 221 | QTableView *table = this->ui->tableView; | ||
454 | QList<MyMoneyAccount> accountList; | 222 | table->resizeColumnsToContents(); | ||
455 | file->accountList(accountList); | 223 | this->repaint(); | ||
456 | QList<MyMoneyAccount> filteredTypes; | | |||
457 | QList<MyMoneyAccount> filteredAccounts; | | |||
458 | QList<MyMoneyAccount>::iterator account; | | |||
459 | QRegExp filterOutChars = QRegExp("-., "); | | |||
460 | | ||||
461 | for (account = accountList.begin(); account != accountList.end(); ++account) { | | |||
462 | if (accountTypes.contains((*account).accountType()) && !(*account).isClosed()) | | |||
463 | filteredTypes << *account; | | |||
464 | } | | |||
465 | 224 | | |||
466 | // filter out accounts whose names aren't in statements header | 225 | QRect screen = QApplication::desktop()->availableGeometry(); //get available screen size | ||
467 | for (account = filteredTypes.begin(); account != filteredTypes.end(); ++account) { | 226 | QRect wizard = this->frameGeometry(); //get current wizard size | ||
468 | QString txt = (*account).name(); | | |||
469 | txt = txt.replace(filterOutChars, ""); | | |||
470 | if (statementHeader.contains(txt, Qt::CaseInsensitive)) | | |||
471 | filteredAccounts << *account; | | |||
472 | } | | |||
473 | 227 | | |||
474 | // if filtering returned more results, filter out accounts whose numbers aren't in statements header | 228 | int newWidth = table->contentsMargins().left() + | ||
475 | if (filteredAccounts.count() > 1) { | 229 | table->contentsMargins().right() + | ||
476 | for (account = filteredAccounts.begin(); account != filteredAccounts.end();) { | 230 | table->horizontalHeader()->length() + | ||
477 | QString txt = (*account).number(); | 231 | table->verticalHeader()->width() + | ||
478 | txt = txt.replace(filterOutChars, ""); | 232 | (wizard.width() - table->width()); | ||
479 | if (txt.isEmpty() || txt.length() < 3) { | 233 | if (table->verticalScrollBar()->isEnabled()) { | ||
480 | ++account; | 234 | if (!table->verticalScrollBar()->isVisible() && // vertical scrollbar may be not visible after repaint... | ||
481 | continue; | 235 | table->horizontalScrollBar()->isVisible()) // ...so use horizontal scrollbar dimension | ||
482 | } | 236 | newWidth += table->horizontalScrollBar()->height(); | ||
483 | if (statementHeader.contains(txt, Qt::CaseInsensitive)) | | |||
484 | ++account; | | |||
485 | else | 237 | else | ||
486 | account = filteredAccounts.erase(account); | 238 | newWidth += table->verticalScrollBar()->width(); | ||
487 | } | | |||
488 | } | 239 | } | ||
489 | 240 | | |||
490 | // if filtering by name and number didn't return nothing, then try filtering by number only | 241 | int newHeight = table->contentsMargins().top() + | ||
491 | if (filteredAccounts.isEmpty()) { | 242 | table->contentsMargins().bottom() + | ||
492 | for (account = filteredTypes.begin(); account != filteredTypes.end(); ++account) { | 243 | table->verticalHeader()->length() + | ||
493 | QString txt = (*account).number(); | 244 | table->horizontalHeader()->height() + | ||
494 | txt = txt.replace(filterOutChars, ""); | 245 | (wizard.height() - table->height()); | ||
495 | if (statementHeader.contains(txt, Qt::CaseInsensitive)) | 246 | | ||
496 | filteredAccounts << *account; | 247 | if (table->horizontalScrollBar()->isEnabled()) { | ||
497 | } | 248 | if (!table->horizontalScrollBar()->isVisible() && // horizontal scrollbar may be not visible after repaint... | ||
498 | } | 249 | table->verticalScrollBar()->isVisible()) // ...so use vertical scrollbar dimension | ||
499 | return filteredAccounts; | 250 | newHeight += table->verticalScrollBar()->width(); | ||
251 | else | ||||
252 | newHeight += table->horizontalScrollBar()->height(); | ||||
500 | } | 253 | } | ||
501 | 254 | | |||
502 | bool CSVWizard::detectAccount(MyMoneyStatement& st) | 255 | // limit wizard size to screen size | ||
503 | { | 256 | if (newHeight > screen.height()) | ||
504 | QString statementHeader; | 257 | newHeight = screen.height(); | ||
505 | for (int row = 0; row < m_startLine - 1; ++row) // concatenate header for better search | | |||
506 | statementHeader += m_lineList.value(row); | | |||
507 | 258 | | |||
508 | QRegExp filterOutChars = QRegExp("-., "); | 259 | if (newWidth > screen.width()) | ||
509 | statementHeader.replace(filterOutChars, ""); | 260 | newWidth = screen.width(); | ||
510 | 261 | | |||
511 | QList<MyMoneyAccount> accounts; | | |||
512 | QList<MyMoneyAccount::accountTypeE> accountTypes; | | |||
513 | 262 | | |||
514 | if (m_profileType == CSVWizard::ProfileBank) { | 263 | // don't shrink wizard if required size is less than initial | ||
515 | accountTypes << MyMoneyAccount::Checkings << | 264 | if (newWidth < this->m_initialWidth) | ||
516 | MyMoneyAccount::Savings << | 265 | newWidth = this->m_initialWidth; | ||
517 | MyMoneyAccount::Liability << | 266 | if (newHeight < this->m_initialHeight) | ||
518 | MyMoneyAccount::Checkings << | 267 | newHeight = this->m_initialHeight; | ||
519 | MyMoneyAccount::Savings << | | |||
520 | MyMoneyAccount::Cash << | | |||
521 | MyMoneyAccount::CreditCard << | | |||
522 | MyMoneyAccount::Loan << | | |||
523 | MyMoneyAccount::Asset << | | |||
524 | MyMoneyAccount::Liability; | | |||
525 | accounts = findAccounts(accountTypes, statementHeader); | | |||
526 | } else if (m_profileType == CSVWizard::ProfileInvest) { | | |||
527 | accountTypes << MyMoneyAccount::Investment; // take investment accounts... | | |||
528 | accounts = findAccounts(accountTypes, statementHeader); //...and search them in statement header | | |||
529 | } | | |||
530 | 268 | | |||
531 | if (accounts.count() == 1) { // set account in statement, if it was the only one match | 269 | newWidth -= (wizard.width() - this->geometry().width()); // remove window frame | ||
532 | st.m_strAccountName = accounts.first().name(); | 270 | newHeight -= (wizard.height() - this->geometry().height()); | ||
533 | st.m_strAccountNumber = accounts.first().number(); | | |||
534 | st.m_accountId = accounts.first().id(); | | |||
535 | 271 | | |||
536 | switch (accounts.first().accountType()) { | 272 | wizard.setWidth(newWidth); | ||
537 | case MyMoneyAccount::Checkings: | 273 | wizard.setHeight(newHeight); | ||
538 | st.m_eType=MyMoneyStatement::etCheckings; | 274 | wizard.moveTo((screen.width() - wizard.width()) / 2, | ||
539 | break; | 275 | (screen.height() - wizard.height()) / 2); | ||
540 | case MyMoneyAccount::Savings: | 276 | this->setGeometry(wizard); | ||
541 | st.m_eType=MyMoneyStatement::etSavings; | | |||
542 | break; | | |||
543 | case MyMoneyAccount::Investment: | | |||
544 | st.m_eType=MyMoneyStatement::etInvestment; | | |||
545 | break; | | |||
546 | case MyMoneyAccount::CreditCard: | | |||
547 | st.m_eType=MyMoneyStatement::etCreditCard; | | |||
548 | break; | | |||
549 | default: | | |||
550 | st.m_eType=MyMoneyStatement::etNone; | | |||
551 | } | | |||
552 | return true; | | |||
553 | } | | |||
554 | return false; | | |||
555 | } | 277 | } | ||
556 | 278 | | |||
557 | bool CSVWizard::detectDecimalSymbol(const int col, int& symbol) | 279 | void CSVWizard::closeEvent(QCloseEvent *event) | ||
558 | { | 280 | { | ||
559 | if (symbol != 2) | 281 | this->m_plugin->m_action->setEnabled(true); // reenable File->Import->CSV | ||
560 | return true; | 282 | event->accept(); | ||
561 | | ||||
562 | // get list of used currencies to remove them from col | | |||
563 | QList<MyMoneyAccount> accountList; | | |||
564 | MyMoneyFile::instance()->accountList(accountList); | | |||
565 | | ||||
566 | QList<MyMoneyAccount::accountTypeE> accountTypes; | | |||
567 | accountTypes << MyMoneyAccount::Checkings << | | |||
568 | MyMoneyAccount::Savings << | | |||
569 | MyMoneyAccount::Liability << | | |||
570 | MyMoneyAccount::Checkings << | | |||
571 | MyMoneyAccount::Savings << | | |||
572 | MyMoneyAccount::Cash << | | |||
573 | MyMoneyAccount::CreditCard << | | |||
574 | MyMoneyAccount::Loan << | | |||
575 | MyMoneyAccount::Asset << | | |||
576 | MyMoneyAccount::Liability; | | |||
577 | | ||||
578 | QSet<QString> currencySymbols; | | |||
579 | for (QList<MyMoneyAccount>::ConstIterator account = accountList.cbegin(); account != accountList.cend(); ++account) { | | |||
580 | if (accountTypes.contains((*account).accountType())) { // account must actually have currency property | | |||
581 | currencySymbols.insert((*account).currencyId()); // add currency id | | |||
582 | currencySymbols.insert(MyMoneyFile::instance()->currency((*account).currencyId()).tradingSymbol()); // add currency symbol | | |||
583 | } | | |||
584 | } | | |||
585 | QString filteredCurrencies = QStringList(currencySymbols.values()).join(""); | | |||
586 | QString pattern = QString("%1%2").arg(QLocale().currencySymbol()).arg(filteredCurrencies); | | |||
587 | QRegularExpression re("^[\\(+-]?\\d+[\\)]?$"); // matches '0' ; '+12' ; '-345' ; '(6789)' | | |||
588 | | ||||
589 | bool dotIsDecimalSeparator = false; | | |||
590 | bool commaIsDecimalSeparator = false; | | |||
591 | for (int row = m_startLine - 1; row < m_endLine; ++row) { | | |||
592 | QString txt = ui->tableWidget->item(row, col)->text(); | | |||
593 | if (txt.isEmpty()) // nothing to process, so go to next row | | |||
594 | continue; | | |||
595 | int dotPos = txt.lastIndexOf("."); // get last positions of decimal/thousand separator... | | |||
596 | int commaPos = txt.lastIndexOf(","); // ...to be able to determine which one is the last | | |||
597 | | ||||
598 | if (dotPos != -1 && commaPos != -1) { | | |||
599 | if (dotPos > commaPos && commaIsDecimalSeparator == false) // follwing case 1,234.56 | | |||
600 | dotIsDecimalSeparator = true; | | |||
601 | else if (dotPos < commaPos && dotIsDecimalSeparator == false) // follwing case 1.234,56 | | |||
602 | commaIsDecimalSeparator = true; | | |||
603 | else // follwing case 1.234,56 and somwhere earlier there was 1,234.56 so unresolvable conflict | | |||
604 | return false; | | |||
605 | } else if (dotPos != -1) { // follwing case 1.23 | | |||
606 | if (dotIsDecimalSeparator) // it's already know that dotIsDecimalSeparator | | |||
607 | continue; | | |||
608 | if (!commaIsDecimalSeparator) // if there is no conflict with comma as decimal separator | | |||
609 | dotIsDecimalSeparator = true; | | |||
610 | else { | | |||
611 | if (txt.count('.') > 1) // follwing case 1.234.567 so OK | | |||
612 | continue; | | |||
613 | else if (txt.length() - 4 == dotPos) // follwing case 1.234 and somwhere earlier there was 1.234,56 so OK | | |||
614 | continue; | | |||
615 | else // follwing case 1.23 and somwhere earlier there was 1,23 so unresolvable conflict | | |||
616 | return false; | | |||
617 | } | | |||
618 | } else if (commaPos != -1) { // follwing case 1,23 | | |||
619 | if (commaIsDecimalSeparator) // it's already know that commaIsDecimalSeparator | | |||
620 | continue; | | |||
621 | else if (!dotIsDecimalSeparator) // if there is no conflict with dot as decimal separator | | |||
622 | commaIsDecimalSeparator = true; | | |||
623 | else { | | |||
624 | if (txt.count(',') > 1) // follwing case 1,234,567 so OK | | |||
625 | continue; | | |||
626 | else if (txt.length() - 4 == commaPos) // follwing case 1,234 and somwhere earlier there was 1,234.56 so OK | | |||
627 | continue; | | |||
628 | else // follwing case 1,23 and somwhere earlier there was 1.23 so unresolvable conflict | | |||
629 | return false; | | |||
630 | } | | |||
631 | | ||||
632 | } else { // follwing case 123 | | |||
633 | txt.remove(QRegularExpression("[ " + QRegularExpression::escape(pattern) + ']')); | | |||
634 | QRegularExpressionMatch match = re.match(txt); | | |||
635 | if (match.hasMatch()) // if string is pure numerical then go forward... | | |||
636 | continue; | | |||
637 | else // ...if not then it's non-numerical garbage | | |||
638 | return false; | | |||
639 | } | | |||
640 | } | 283 | } | ||
641 | 284 | | |||
642 | if (dotIsDecimalSeparator) | 285 | bool CSVWizard::eventFilter(QObject *object, QEvent *event) | ||
643 | symbol = 0; | 286 | { | ||
644 | else if (commaIsDecimalSeparator) | 287 | // prevent the QWizard part of CSVWizard window from closing on Escape key press | ||
645 | symbol = 1; | 288 | if (object == this->m_wiz) { | ||
646 | else { // whole column was empty, but we don't want to fail so take os decimal symbol | 289 | if (event->type() == QEvent::KeyPress) { | ||
647 | if (QLocale().decimalPoint() == '.') | 290 | QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event); | ||
648 | symbol = 0; | 291 | if (keyEvent->key() == Qt::Key_Escape) { | ||
649 | else | 292 | close(); | ||
650 | symbol = 1; | | |||
651 | } | | |||
652 | return true; | 293 | return true; | ||
653 | } | 294 | } | ||
654 | | ||||
655 | int CSVWizard::getMaxColumnCount(QStringList &lineList, int &delimiter) | | |||
656 | { | | |||
657 | if (lineList.isEmpty()) | | |||
658 | return 0; | | |||
659 | | ||||
660 | QList<int> delimiterIndexes; | | |||
661 | if (delimiter == -1) | | |||
662 | delimiterIndexes = QList<int>{0, 1, 2, 3}; // include all delimiters to test or ... | | |||
663 | else | | |||
664 | delimiterIndexes = QList<int>{delimiter}; // ... only the one specified | | |||
665 | | ||||
666 | int totalDelimiterCount[4] = {0}; // Total in file for each delimiter | | |||
667 | int thisDelimiterCount[4] = {0}; // Total in this line for each delimiter | | |||
668 | int colCount = 0; // Total delimiters in this line | | |||
669 | int possibleDelimiter = 0; | | |||
670 | int maxColumnCount = 0; | | |||
671 | | ||||
672 | for (int i = 0; i < lineList.count(); i++) { | | |||
673 | QString data = lineList[i]; | | |||
674 | | ||||
675 | for (QList<int>::ConstIterator it = delimiterIndexes.constBegin(); it != delimiterIndexes.constEnd(); it++) { | | |||
676 | m_parse->setFieldDelimiterIndex(*it); | | |||
677 | colCount = m_parse->parseLine(data).count(); // parse each line using each delimiter | | |||
678 | | ||||
679 | if (colCount > thisDelimiterCount[*it]) | | |||
680 | thisDelimiterCount[*it] = colCount; | | |||
681 | | ||||
682 | if (thisDelimiterCount[*it] > maxColumnCount) | | |||
683 | maxColumnCount = thisDelimiterCount[*it]; | | |||
684 | | ||||
685 | totalDelimiterCount[*it] += colCount; | | |||
686 | if (totalDelimiterCount[*it] > totalDelimiterCount[possibleDelimiter]) | | |||
687 | possibleDelimiter = *it; | | |||
688 | } | | |||
689 | } | | |||
690 | delimiter = possibleDelimiter; | | |||
691 | m_parse->setFieldDelimiterIndex(delimiter); | | |||
692 | return maxColumnCount; | | |||
693 | } | | |||
694 | | ||||
695 | bool CSVWizard::getInFileName(QString& inFileName) | | |||
696 | { | | |||
697 | if (inFileName.isEmpty()) | | |||
698 | inFileName = QDir::homePath(); | | |||
699 | | ||||
700 | if(inFileName.startsWith("~/")) //expand Linux home directory | | |||
701 | inFileName.replace(0, 1, QDir::home().absolutePath()); | | |||
702 | | ||||
703 | QFileInfo fileInfo = QFileInfo(inFileName); | | |||
704 | if (fileInfo.isFile()) { // if it is file... | | |||
705 | if (fileInfo.exists()) // ...and exists... | | |||
706 | return true; // ...then all is OK... | | |||
707 | else { // ...but if not... | | |||
708 | fileInfo.setFile(fileInfo.absolutePath()); //...then set start directory to directory of that file... | | |||
709 | if (!fileInfo.exists()) //...and if it doesn't exist too... | | |||
710 | fileInfo.setFile(QDir::homePath()); //...then set start directory to home path | | |||
711 | } | | |||
712 | } | | |||
713 | | ||||
714 | QPointer<QFileDialog> dialog = new QFileDialog(this, QString(), | | |||
715 | fileInfo.absoluteFilePath(), | | |||
716 | i18n("CSV Files (*.csv)")); | | |||
717 | dialog->setOption(QFileDialog::DontUseNativeDialog, true); //otherwise we cannot add custom QComboBox | | |||
718 | dialog->setFileMode(QFileDialog::ExistingFile); | | |||
719 | QPointer<QLabel> label = new QLabel(i18n("Encoding")); | | |||
720 | dialog->layout()->addWidget(label); | | |||
721 | // Add encoding selection to FileDialog | | |||
722 | QPointer<QComboBox> comboBoxEncode = new QComboBox(); | | |||
723 | setCodecList(m_codecs, comboBoxEncode); | | |||
724 | comboBoxEncode->setCurrentIndex(m_encodeIndex); | | |||
725 | connect(comboBoxEncode, SIGNAL(activated(int)), this, SLOT(encodingChanged(int))); | | |||
726 | dialog->layout()->addWidget(comboBoxEncode); | | |||
727 | QUrl url; | | |||
728 | if (dialog->exec() == QDialog::Accepted) | | |||
729 | url = dialog->selectedUrls().first(); | | |||
730 | else | | |||
731 | url.clear(); | | |||
732 | delete dialog; | | |||
733 | | ||||
734 | if (url.isEmpty()) | | |||
735 | return false; | | |||
736 | else if (url.isLocalFile()) | | |||
737 | inFileName = url.toLocalFile(); | | |||
738 | else { | | |||
739 | inFileName = QDir::tempPath(); | | |||
740 | if (!inFileName.endsWith(QDir::separator())) | | |||
741 | inFileName += QDir::separator(); | | |||
742 | inFileName += url.fileName(); | | |||
743 | qDebug() << "Source:" << url.toDisplayString() << "Destination:" << inFileName; | | |||
744 | KIO::FileCopyJob *job = KIO::file_copy(url, QUrl::fromUserInput(inFileName), | | |||
745 | -1, KIO::Overwrite); | | |||
746 | KJobWidgets::setWindow(job, this); | | |||
747 | job->exec(); | | |||
748 | if (job->error()) { | | |||
749 | KMessageBox::detailedError(this, | | |||
750 | i18n("Error while loading file '%1'.", url.toDisplayString()), | | |||
751 | job->errorString(), | | |||
752 | i18n("File access error")); | | |||
753 | return false; | | |||
754 | } | 295 | } | ||
755 | } | 296 | } | ||
756 | | ||||
757 | if (inFileName.isEmpty()) | | |||
758 | return false; | 297 | return false; | ||
759 | return true; | | |||
760 | } | 298 | } | ||
761 | 299 | | |||
762 | void CSVWizard::encodingChanged(int index) | 300 | void CSVWizard::slotClose() | ||
763 | { | 301 | { | ||
764 | m_encodeIndex = index; | 302 | m_imp->m_profile->m_lastUsedDirectory = m_imp->m_file->m_inFileName; | ||
303 | m_imp->m_profile->writeSettings(CSVImporter::configFile()); | ||||
304 | m_imp->profilesAction(m_imp->m_profile->type(), ProfilesUpdateLastUsed, m_imp->m_profile->m_profileName, m_imp->m_profile->m_profileName); | ||||
305 | close(); | ||||
765 | } | 306 | } | ||
766 | 307 | | |||
767 | void CSVWizard::readFile(const QString& fname) | 308 | void CSVWizard::fileDialogClicked() | ||
768 | { | 309 | { | ||
769 | if (!fname.isEmpty()) | 310 | m_imp->profileFactory(m_pageIntro->m_profileType, m_pageIntro->ui->m_profiles->currentText()); | ||
770 | m_inFileName = fname; | 311 | bool profileExists = m_imp->m_profile->readSettings(CSVImporter::configFile()); | ||
771 | | ||||
772 | m_importError = false; | | |||
773 | | ||||
774 | QFile inFile(m_inFileName); | | |||
775 | inFile.open(QIODevice::ReadOnly); // allow a Carriage return -// QIODevice::Text | | |||
776 | QTextStream inStream(&inFile); | | |||
777 | QTextCodec* codec = QTextCodec::codecForMib(m_codecs.value(m_encodeIndex)->mibEnum()); | | |||
778 | inStream.setCodec(codec); | | |||
779 | | ||||
780 | QString buf = inStream.readAll(); | | |||
781 | inFile.close(); | | |||
782 | m_lineList = m_parse->parseFile(buf, 1, 0); // parse the buffer | | |||
783 | m_fileEndLine = m_parse->lastLine(); // won't work without above line | | |||
784 | 312 | | |||
785 | if (m_fileEndLine > m_trailerLines) | 313 | if (!m_imp->m_file->getInFileName(m_imp->m_profile->m_lastUsedDirectory)) | ||
786 | m_endLine = m_fileEndLine - m_trailerLines; | 314 | return; | ||
787 | else | | |||
788 | m_endLine = m_fileEndLine; // Ignore m_trailerLines as > file length. | | |||
789 | | ||||
790 | if (m_startLine > m_endLine) // Don't allow m_startLine > m_endLine | | |||
791 | m_startLine = m_endLine; | | |||
792 | } | | |||
793 | | ||||
794 | void CSVWizard::displayLines(const QStringList &lineList, Parse* parse) | | |||
795 | { | | |||
796 | ui->tableWidget->clear(); | | |||
797 | m_row = 0; | | |||
798 | QFont font(QApplication::font()); | | |||
799 | ui->tableWidget->setFont(font); | | |||
800 | ui->tableWidget->setRowCount(lineList.count()); | | |||
801 | ui->tableWidget->setColumnCount(m_maxColumnCount); | | |||
802 | 315 | | |||
803 | for (int line = 0; line < lineList.count(); ++line) { | 316 | saveWindowSize(CSVImporter::configFile()); | ||
804 | QStringList columnList = parse->parseLine(lineList[line]); | 317 | m_imp->m_file->readFile(m_imp->m_profile); | ||
805 | for (int col = 0; col < columnList.count(); ++col) { | 318 | m_imp->m_file->setupParser(m_imp->m_profile); | ||
806 | QTableWidgetItem *item = new QTableWidgetItem; // new item for tableWidget | 319 | | ||
807 | item->setText(columnList[col]); | 320 | m_skipSetup = m_pageIntro->ui->m_skipSetup->isChecked(); | ||
808 | ui->tableWidget->setItem(m_row, col, item); // add item to tableWidget | 321 | | ||
809 | } | 322 | switch(m_imp->m_profile->type()) { | ||
810 | if (columnList.count() < m_maxColumnCount) { // if 'header' area has less columns than 'data' area, then fill this area with whitespaces for nice effect with markUnwantedRows | 323 | case ProfileInvest: | ||
811 | for (int col = columnList.count(); col < m_maxColumnCount; ++col) { | 324 | if (!m_pageInvestment) { | ||
812 | QTableWidgetItem *item = new QTableWidgetItem; // new item for tableWidget | 325 | m_pageInvestment = new InvestmentPage(this, m_imp); | ||
813 | item->setText(""); | 326 | m_wiz->setPage(CSVWizard::PageInvestment, m_pageInvestment); | ||
814 | ui->tableWidget->setItem(m_row, col, item); // add item to tableWidget | | |||
815 | } | 327 | } | ||
328 | break; | ||||
329 | case ProfileBank: | ||||
330 | if (!m_pageBanking) { | ||||
331 | m_pageBanking = new BankingPage(this, m_imp); | ||||
332 | m_wiz->setPage(CSVWizard::PageBanking, m_pageBanking); | ||||
816 | } | 333 | } | ||
817 | m_row ++; | 334 | break; | ||
335 | case ProfileStockPrices: | ||||
336 | case ProfileCurrencyPrices: | ||||
337 | if (!m_pagePrices) { | ||||
338 | m_pagePrices = new PricesPage(this, m_imp); | ||||
339 | m_wiz->setPage(CSVWizard::PagePrices, m_pagePrices); | ||||
818 | } | 340 | } | ||
819 | 341 | break; | |||
820 | for (int col = 0; col < ui->tableWidget->columnCount(); col ++) | 342 | default: | ||
821 | ui->tableWidget->resizeColumnToContents(col); | 343 | return; | ||
822 | } | 344 | } | ||
823 | 345 | | |||
824 | void CSVWizard::updateWindowSize() | 346 | m_wiz->next(); //go to separator page | ||
825 | { | | |||
826 | QTableWidget *table = this->ui->tableWidget; | | |||
827 | table->resizeColumnsToContents(); | | |||
828 | layout()->invalidate(); | | |||
829 | layout()->activate(); | | |||
830 | | ||||
831 | QRect screen = QApplication::desktop()->availableGeometry(); //get available screen size | | |||
832 | QRect wizard = this->frameGeometry(); //get current wizard size | | |||
833 | | ||||
834 | int newWidth = table->verticalHeader()->width() + //take header, margins nad scrollbar into account | | |||
835 | table->contentsMargins().left() + | | |||
836 | table->contentsMargins().right(); | | |||
837 | if (table->verticalScrollBar()->isEnabled()) | | |||
838 | newWidth += table->verticalScrollBar()->width(); | | |||
839 | for(int i = 0; i < table->columnCount(); ++i) | | |||
840 | newWidth += table->columnWidth(i); //add up required column widths | | |||
841 | | ||||
842 | int newHeight = table->horizontalHeader()->height() + | | |||
843 | table->horizontalScrollBar()->height() + | | |||
844 | table->contentsMargins().top() + | | |||
845 | table->contentsMargins().bottom(); | | |||
846 | if (table->horizontalScrollBar()->isEnabled()) | | |||
847 | newHeight += table->horizontalScrollBar()->height(); | | |||
848 | 347 | | |||
849 | if( this->ui->tableWidget->rowCount() > 0) | 348 | if (m_skipSetup && profileExists) | ||
850 | newHeight += this->ui->tableWidget->rowCount() * table->rowHeight(0); //add up estimated row heights | 349 | for (int i = 0; i < 4; i++) //programmaticaly go through separator-, rows-, investment-/bank-, formatspage | ||
851 | 350 | m_wiz->next(); | |||
852 | newWidth = wizard.width() + (newWidth - table->width()); | | |||
853 | newHeight = wizard.height() + (newHeight - table->height()); | | |||
854 | | ||||
855 | if (newWidth > screen.width()) //limit wizard size to screen size | | |||
856 | newWidth = screen.width(); | | |||
857 | if (newHeight > screen.height()) | | |||
858 | newHeight = screen.height(); | | |||
859 | | ||||
860 | if (newWidth < this->m_initialWidth) //don't shrink wizard if required size is less than initial | | |||
861 | newWidth = this->m_initialWidth; | | |||
862 | if (newHeight < this->m_initialHeight) | | |||
863 | newHeight = this->m_initialHeight; | | |||
864 | | ||||
865 | newWidth -= (wizard.width() - this->geometry().width()); // remove window frame | | |||
866 | newHeight -= (wizard.height() - this->geometry().height()); | | |||
867 | | ||||
868 | wizard.setWidth(newWidth); | | |||
869 | wizard.setHeight(newHeight); | | |||
870 | wizard.moveTo((screen.width() - wizard.width()) / 2, | | |||
871 | (screen.height() - wizard.height()) / 2); | | |||
872 | this->setGeometry(wizard); | | |||
873 | } | 351 | } | ||
874 | 352 | | |||
875 | void CSVWizard::slotFileDialogClicked() | 353 | void CSVWizard::importClicked() | ||
876 | { | 354 | { | ||
877 | saveWindowSize(m_config); | 355 | switch (m_imp->m_profile->type()) { | ||
878 | if (!m_pageInvestment.isNull()) | 356 | case ProfileBank: | ||
879 | m_wizard->removePage(PageInvestment); | 357 | if (!m_pageBanking->validateCreditDebit()) | ||
880 | delete m_pageInvestment; | 358 | return; | ||
881 | if (!m_pageBanking.isNull()) | 359 | break; | ||
882 | m_wizard->removePage(PageBanking); | 360 | case ProfileInvest: | ||
883 | delete m_pageBanking; | 361 | if (!m_pageInvestment->validateActionType()) | ||
884 | 362 | return; | |||
885 | m_profileName = m_pageIntro->ui->combobox_source->currentText(); | 363 | break; | ||
886 | m_skipSetup = m_pageIntro->ui->checkBoxSkipSetup->isChecked(); | 364 | default: | ||
887 | m_accept = false; | 365 | break; | ||
888 | m_acceptAllInvalid = false; // Don't accept further invalid values. | | |||
889 | m_memoColList.clear(); | | |||
890 | | ||||
891 | if (m_profileType == CSVWizard::ProfileInvest) { | | |||
892 | m_pageInvestment = new InvestmentPage; | | |||
893 | m_wizard->setPage(PageInvestment, m_pageInvestment); | | |||
894 | m_pageInvestment->setParent(this); | | |||
895 | m_pageInvestment->readSettings(m_config); | | |||
896 | } | | |||
897 | else if (m_profileType == CSVWizard::ProfileBank) { | | |||
898 | m_pageBanking = new BankingPage; | | |||
899 | m_wizard->setPage(PageBanking, m_pageBanking); | | |||
900 | m_pageBanking->setParent(this); | | |||
901 | m_pageBanking->readSettings(m_config); | | |||
902 | } | | |||
903 | else if (m_profileType == CSVWizard::ProfileStockPrices || | | |||
904 | m_profileType == CSVWizard::ProfileCurrencyPrices) { | | |||
905 | m_pagePrices = new PricesPage; | | |||
906 | m_wizard->setPage(PagePrices, m_pagePrices); | | |||
907 | m_pagePrices->setParent(this); | | |||
908 | m_pagePrices->readSettings(m_config); | | |||
909 | } | 366 | } | ||
910 | 367 | | |||
911 | 368 | if (!m_imp->createStatement(m_st)) | |||
912 | if (!getInFileName(m_inFileName)) | | |||
913 | return; | 369 | return; | ||
914 | readFile(m_inFileName); | 370 | slotClose(); | ||
915 | 371 | emit m_imp->statementReady(m_st); | |||
916 | m_wizard->next(); //go to separator page | | |||
917 | | ||||
918 | if (m_skipSetup) | | |||
919 | for (int i = 0; i < 4; i++) //programmaticaly go through separator-, rows-, investment-/bank-, formatspage | | |||
920 | m_wizard->next(); | | |||
921 | } | 372 | } | ||
922 | 373 | | |||
923 | void CSVWizard::resizeEvent(QResizeEvent* ev) | 374 | void CSVWizard::saveAsQIFClicked() | ||
924 | { | 375 | { | ||
925 | if (ev->spontaneous()) { | 376 | switch (m_imp->m_profile->type()) { | ||
926 | ev->ignore(); | 377 | case ProfileBank: | ||
378 | if (!m_pageBanking->validateCreditDebit()) | ||||
927 | return; | 379 | return; | ||
928 | } | 380 | break; | ||
381 | case ProfileInvest: | ||||
382 | if (!m_pageInvestment->validateActionType()) | ||||
383 | return; | ||||
384 | break; | ||||
385 | default: | ||||
386 | break; | ||||
929 | } | 387 | } | ||
930 | 388 | | |||
931 | void CSVWizard::slotClose() | 389 | bool isOK = m_imp->createStatement(m_st); | ||
932 | { | 390 | if (!isOK || m_st.m_listTransactions.isEmpty()) | ||
933 | if (m_profileType == ProfileBank) | 391 | return; | ||
934 | m_pageBanking->saveSettings(); | 392 | | ||
935 | else if (m_profileType == ProfileInvest) | 393 | QString outFileName = m_imp->m_file->m_inFileName; | ||
936 | m_pageInvestment->saveSettings(); | 394 | outFileName.truncate(outFileName.lastIndexOf('.')); | ||
937 | else if (m_profileType == ProfileStockPrices || | 395 | outFileName.append(QLatin1String(".qif")); | ||
938 | m_profileType == ProfileCurrencyPrices) | 396 | outFileName = QFileDialog::getSaveFileName(this, i18n("Save QIF"), outFileName, i18n("QIF Files (*.qif)")); | ||
939 | m_pagePrices->saveSettings(); | 397 | if (outFileName.isEmpty()) | ||
940 | close(); | 398 | return; | ||
399 | QFile oFile(outFileName); | ||||
400 | oFile.open(QIODevice::WriteOnly); | ||||
401 | switch (m_imp->m_profile->type()) { | ||||
402 | case ProfileBank: | ||||
403 | m_pageBanking->makeQIF(m_st, oFile); | ||||
404 | break; | ||||
405 | case ProfileInvest: | ||||
406 | m_pageInvestment->makeQIF(m_st, oFile); | ||||
407 | break; | ||||
408 | default: | ||||
409 | break; | ||||
410 | } | ||||
411 | oFile.close(); | ||||
941 | } | 412 | } | ||
942 | 413 | | |||
943 | //------------------------------------------------------------------------------------------------------- | 414 | //------------------------------------------------------------------------------------------------------- | ||
944 | IntroPage::IntroPage(QDialog *parent) : | 415 | IntroPage::IntroPage(CSVWizard *dlg, CSVImporter *imp) : | ||
945 | CSVWizardPage(parent), | 416 | CSVWizardPage(dlg, imp), | ||
946 | ui(new Ui::IntroPage), | 417 | ui(new Ui::IntroPage), | ||
947 | m_pageLayout(0) | 418 | m_pageLayout(0) | ||
948 | { | 419 | { | ||
949 | ui->setupUi(this); | 420 | ui->setupUi(this); | ||
950 | } | 421 | } | ||
951 | 422 | | |||
952 | IntroPage::~IntroPage() | 423 | IntroPage::~IntroPage() | ||
953 | { | 424 | { | ||
954 | delete ui; | 425 | delete ui; | ||
955 | } | 426 | } | ||
956 | 427 | | |||
957 | void IntroPage::setParent(CSVWizard* dlg) | 428 | int IntroPage::nextId() const | ||
958 | { | 429 | { | ||
959 | CSVWizardPage::setParent(dlg); | 430 | return CSVWizard::PageSeparator; | ||
960 | m_wizDlg->showStage(); | 431 | } | ||
961 | 432 | | |||
962 | wizard()->button(QWizard::CustomButton1)->setEnabled(false); | 433 | void IntroPage::initializePage() | ||
434 | { | ||||
435 | m_imp->m_file->m_model->clear(); | ||||
436 | | ||||
437 | wizard()->setButtonText(QWizard::CustomButton1, i18n("Select File")); | ||||
438 | wizard()->button(QWizard::CustomButton1)->setToolTip(i18n("A profile must be selected before selecting a file.")); | ||||
439 | QList<QWizard::WizardButton> layout; | ||||
440 | layout << QWizard::Stretch << | ||||
441 | QWizard::CustomButton1 << | ||||
442 | QWizard::CancelButton; | ||||
443 | wizard()->setButtonLayout(layout); | ||||
444 | | ||||
445 | ui->m_profiles->lineEdit()->setClearButtonEnabled(true); | ||||
446 | | ||||
447 | connect(ui->m_profiles, SIGNAL(currentIndexChanged(int)), this, SLOT(slotComboSourceIndexChanged(int))); | ||||
448 | connect(ui->m_add, SIGNAL(clicked()), this, SLOT(slotAddProfile())); | ||||
449 | connect(ui->m_remove, SIGNAL(clicked()), this, SLOT(slotRemoveProfile())); | ||||
450 | connect(ui->m_rename, SIGNAL(clicked()), this, SLOT(slotRenameProfile())); | ||||
451 | connect(ui->m_profilesBank, SIGNAL(toggled(bool)), this, SLOT(slotBankRadioToggled(bool))); | ||||
452 | connect(ui->m_profilesInvest, SIGNAL(toggled(bool)), this, SLOT(slotInvestRadioToggled(bool))); | ||||
453 | connect(ui->m_profilesCurrencyPrices, SIGNAL(toggled(bool)), this, SLOT(slotCurrencyPricesRadioToggled(bool))); | ||||
454 | connect(ui->m_profilesStockPrices, SIGNAL(toggled(bool)), this, SLOT(slotStockPricesRadioToggled(bool))); | ||||
455 | if (m_dlg->m_initialHeight == -1 || m_dlg->m_initialWidth == -1) { | ||||
456 | m_dlg->m_initialHeight = m_dlg->geometry().height(); | ||||
457 | m_dlg->m_initialWidth = m_dlg->geometry().width(); | ||||
458 | } else { | ||||
459 | //resize wizard to its initial size and center it | ||||
460 | m_dlg->setGeometry( | ||||
461 | QStyle::alignedRect( | ||||
462 | Qt::LeftToRight, | ||||
463 | Qt::AlignCenter, | ||||
464 | QSize(m_dlg->m_initialWidth, m_dlg->m_initialHeight), | ||||
465 | QApplication::desktop()->availableGeometry() | ||||
466 | ) | ||||
467 | ); | ||||
468 | } | ||||
469 | } | ||||
470 | | ||||
471 | bool IntroPage::validatePage() | ||||
472 | { | ||||
473 | return true; | ||||
963 | } | 474 | } | ||
964 | 475 | | |||
965 | void IntroPage::slotAddProfile() | 476 | void IntroPage::slotAddProfile() | ||
966 | { | 477 | { | ||
967 | profileChanged(ProfileAdd); | 478 | profileChanged(ProfilesAdd); | ||
968 | } | 479 | } | ||
969 | 480 | | |||
970 | void IntroPage::slotRemoveProfile() | 481 | void IntroPage::slotRemoveProfile() | ||
971 | { | 482 | { | ||
972 | profileChanged(ProfileRemove); | 483 | profileChanged(ProfilesRemove); | ||
973 | } | 484 | } | ||
974 | 485 | | |||
975 | void IntroPage::slotRenameProfile() | 486 | void IntroPage::slotRenameProfile() | ||
976 | { | 487 | { | ||
977 | profileChanged(ProfileRename); | 488 | profileChanged(ProfilesRename); | ||
978 | } | 489 | } | ||
979 | 490 | | |||
980 | void IntroPage::profileChanged(const profileActionsE& action) | 491 | void IntroPage::profileChanged(const profilesActionE action) | ||
981 | { | 492 | { | ||
982 | int cbIndex = ui->combobox_source->currentIndex(); | 493 | QString cbText = ui->m_profiles->currentText(); | ||
983 | QString cbText = ui->combobox_source->currentText(); | | |||
984 | if (cbText.isEmpty()) // you cannot neither add nor remove empty name profile or rename to empty name | 494 | if (cbText.isEmpty()) // you cannot neither add nor remove empty name profile or rename to empty name | ||
985 | return; | 495 | return; | ||
986 | 496 | | |||
987 | QString profileTypeStr; | 497 | int cbIndex = ui->m_profiles->currentIndex(); | ||
988 | if (m_wizDlg->m_profileType == CSVWizard::ProfileBank) | | |||
989 | profileTypeStr = "Bank"; | | |||
990 | else if (m_wizDlg->m_profileType == CSVWizard::ProfileInvest) | | |||
991 | profileTypeStr = "Invest"; | | |||
992 | else if (m_wizDlg->m_profileType == CSVWizard::ProfileStockPrices) | | |||
993 | profileTypeStr = "SPrices"; | | |||
994 | else if (m_wizDlg->m_profileType == CSVWizard::ProfileCurrencyPrices) | | |||
995 | profileTypeStr = "CPrices"; | | |||
996 | | ||||
997 | KConfigGroup profileNamesGroup(m_wizDlg->m_config, "ProfileNames"); | | |||
998 | KConfigGroup currentProfileName(m_wizDlg->m_config, profileTypeStr + '-' + cbText); | | |||
999 | if (action == ProfileRemove) { | | |||
1000 | if (m_wizDlg->m_profileList.value(cbIndex) != cbText) | | |||
1001 | return; | | |||
1002 | m_wizDlg->m_profileList.removeAt(cbIndex); | | |||
1003 | currentProfileName.deleteGroup(); | | |||
1004 | ui->combobox_source->removeItem(cbIndex); | | |||
1005 | KMessageBox::information(m_wizDlg->m_wizard, | | |||
1006 | i18n("<center>Profile <b>%1</b> has been removed.</center>", | | |||
1007 | cbText)); | | |||
1008 | } | | |||
1009 | 498 | | |||
1010 | if (action == ProfileAdd || action == ProfileRename) { | 499 | switch (action) { | ||
1011 | int dupIndex = m_wizDlg->m_profileList.indexOf(cbText, Qt::CaseInsensitive); | 500 | case ProfilesRename: | ||
501 | case ProfilesAdd: | ||||
502 | { | ||||
503 | int dupIndex = m_profiles.indexOf(QRegularExpression (cbText)); | ||||
1012 | if (dupIndex == cbIndex && cbIndex != -1) // if profile name wasn't changed then return | 504 | if (dupIndex == cbIndex && cbIndex != -1) // if profile name wasn't changed then return | ||
1013 | return; | 505 | return; | ||
1014 | else if (dupIndex != -1) { // profile with the same name already exists | 506 | else if (dupIndex != -1) { // profile with the same name already exists | ||
1015 | ui->combobox_source->setItemText(cbIndex, m_wizDlg->m_profileList.value(cbIndex)); | 507 | ui->m_profiles->setItemText(cbIndex, m_profiles.value(cbIndex)); | ||
1016 | KMessageBox::information(m_wizDlg->m_wizard, | 508 | KMessageBox::information(m_dlg, | ||
1017 | i18n("<center>Profile <b>%1</b> already exists.<br>" | 509 | i18n("<center>Profile <b>%1</b> already exists.<br>" | ||
1018 | "Please enter another name</center>", cbText)); | 510 | "Please enter another name</center>", cbText)); | ||
1019 | return; | 511 | return; | ||
1020 | } | 512 | } | ||
513 | break; | ||||
514 | } | ||||
515 | case ProfilesRemove: | ||||
516 | if (m_profiles.value(cbIndex) != cbText) // user changed name of the profile and tries to remove it | ||||
517 | return; | ||||
518 | break; | ||||
519 | default: | ||||
520 | break; | ||||
521 | } | ||||
1021 | 522 | | |||
1022 | if (action == ProfileAdd) { | 523 | if (CSVImporter::profilesAction(m_profileType, action, m_profiles.value(cbIndex), cbText)) { | ||
1023 | m_wizDlg->m_profileList.append(cbText); | 524 | switch (action) { | ||
1024 | ui->combobox_source->addItem(cbText); | 525 | case ProfilesAdd: | ||
1025 | ui->combobox_source->setCurrentIndex(m_wizDlg->m_profileList.count() - 1); | 526 | m_profiles.append(cbText); | ||
1026 | currentProfileName.writeEntry("Directory", QString()); | 527 | ui->m_profiles->addItem(cbText); | ||
1027 | KMessageBox::information(m_wizDlg->m_wizard, | 528 | ui->m_profiles->setCurrentIndex(m_profiles.count() - 1); | ||
529 | KMessageBox::information(m_dlg, | ||||
1028 | i18n("<center>Profile <b>%1</b> has been added.</center>", cbText)); | 530 | i18n("<center>Profile <b>%1</b> has been added.</center>", cbText)); | ||
1029 | } else if (action == ProfileRename) { | 531 | break; | ||
1030 | KConfigGroup oldProfileName(m_wizDlg->m_config, profileTypeStr + '-' + m_wizDlg->m_profileList.value(cbIndex)); | 532 | case ProfilesRemove: | ||
1031 | oldProfileName.copyTo(¤tProfileName); | 533 | m_profiles.removeAt(cbIndex); | ||
1032 | oldProfileName.deleteGroup(); | 534 | ui->m_profiles->removeItem(cbIndex); | ||
1033 | ui->combobox_source->setItemText(cbIndex, cbText); | 535 | KMessageBox::information(m_dlg, | ||
1034 | oldProfileName.sync(); | 536 | i18n("<center>Profile <b>%1</b> has been removed.</center>", | ||
1035 | KMessageBox::information(m_wizDlg->m_wizard, | 537 | cbText)); | ||
538 | break; | ||||
539 | case ProfilesRename: | ||||
540 | ui->m_profiles->setItemText(cbIndex, cbText); | ||||
541 | KMessageBox::information(m_dlg, | ||||
1036 | i18n("<center>Profile name has been renamed from <b>%1</b> to <b>%2</b>.</center>", | 542 | i18n("<center>Profile name has been renamed from <b>%1</b> to <b>%2</b>.</center>", | ||
1037 | m_wizDlg->m_profileList.value(cbIndex), cbText)); | 543 | m_profiles.value(cbIndex), cbText)); | ||
1038 | m_wizDlg->m_profileList[cbIndex] = cbText; | 544 | m_profiles[cbIndex] = cbText; | ||
545 | break; | ||||
546 | default: | ||||
547 | break; | ||||
1039 | } | 548 | } | ||
1040 | } | 549 | } | ||
1041 | currentProfileName.sync(); | | |||
1042 | profileNamesGroup.writeEntry(profileTypeStr, m_wizDlg->m_profileList); // update profiles list | | |||
1043 | profileNamesGroup.sync(); | | |||
1044 | } | 550 | } | ||
1045 | 551 | | |||
1046 | void IntroPage::slotComboSourceIndexChanged(int idx) | 552 | void IntroPage::slotComboSourceIndexChanged(int idx) | ||
1047 | { | 553 | { | ||
1048 | if (idx == -1) { | 554 | if (idx == -1) { | ||
1049 | wizard()->button(QWizard::CustomButton1)->setEnabled(false); | 555 | wizard()->button(QWizard::CustomButton1)->setEnabled(false); | ||
1050 | ui->checkBoxSkipSetup->setEnabled(false); | 556 | ui->m_skipSetup->setEnabled(false); | ||
1051 | ui->buttonRemove->setEnabled(false); | 557 | ui->m_remove->setEnabled(false); | ||
1052 | ui->buttonRename->setEnabled(false); | 558 | ui->m_rename->setEnabled(false); | ||
1053 | } | 559 | } | ||
1054 | else { | 560 | else { | ||
1055 | wizard()->button(QWizard::CustomButton1)->setEnabled(true); | 561 | wizard()->button(QWizard::CustomButton1)->setEnabled(true); | ||
1056 | ui->checkBoxSkipSetup->setEnabled(true); | 562 | ui->m_skipSetup->setEnabled(true); | ||
1057 | ui->buttonRemove->setEnabled(true); | 563 | ui->m_remove->setEnabled(true); | ||
1058 | ui->buttonRename->setEnabled(true); | 564 | ui->m_rename->setEnabled(true); | ||
1059 | } | 565 | } | ||
1060 | } | 566 | } | ||
1061 | 567 | | |||
1062 | void IntroPage::profileTypeChanged(const CSVWizard::profileTypeE profileType, bool toggled) | 568 | void IntroPage::profileTypeChanged(const profileTypeE profileType, bool toggled) | ||
1063 | { | 569 | { | ||
1064 | if (!toggled) | 570 | if (!toggled) | ||
1065 | return; | 571 | return; | ||
1066 | 572 | | |||
1067 | KConfigGroup profilesGroup(m_wizDlg->m_config, "ProfileNames"); | 573 | KConfigGroup profilesGroup(CSVImporter::configFile(), CSVImporter::m_confProfileNames); | ||
1068 | m_wizDlg->m_profileType = profileType; | 574 | m_profileType = profileType; | ||
1069 | QString profileTypeStr; | 575 | QString profileTypeStr; | ||
1070 | int priorProfile; | 576 | switch (m_profileType) { | ||
1071 | if (m_wizDlg->m_profileType == CSVWizard::ProfileBank) { | 577 | case ProfileBank: | ||
1072 | ui->radioButton_invest->setChecked(false); | 578 | ui->m_profilesInvest->setChecked(false); | ||
1073 | ui->radioButton_stockprices->setChecked(false); | 579 | ui->m_profilesStockPrices->setChecked(false); | ||
1074 | ui->radioButton_currencyprices->setChecked(false); | 580 | ui->m_profilesCurrencyPrices->setChecked(false); | ||
1075 | profileTypeStr = "Bank"; | 581 | break; | ||
1076 | } else if (m_wizDlg->m_profileType == CSVWizard::ProfileInvest) { | 582 | case ProfileInvest: | ||
1077 | ui->radioButton_bank->setChecked(false); | 583 | ui->m_profilesBank->setChecked(false); | ||
1078 | ui->radioButton_stockprices->setChecked(false); | 584 | ui->m_profilesStockPrices->setChecked(false); | ||
1079 | ui->radioButton_currencyprices->setChecked(false); | 585 | ui->m_profilesCurrencyPrices->setChecked(false); | ||
1080 | profileTypeStr = "Invest"; | 586 | break; | ||
1081 | } else if (m_wizDlg->m_profileType == CSVWizard::ProfileStockPrices) { | 587 | case ProfileStockPrices: | ||
1082 | ui->radioButton_bank->setChecked(false); | 588 | ui->m_profilesBank->setChecked(false); | ||
1083 | ui->radioButton_invest->setChecked(false); | 589 | ui->m_profilesInvest->setChecked(false); | ||
1084 | ui->radioButton_currencyprices->setChecked(false); | 590 | ui->m_profilesCurrencyPrices->setChecked(false); | ||
1085 | profileTypeStr = "SPrices"; | 591 | break; | ||
1086 | } else if (m_wizDlg->m_profileType == CSVWizard::ProfileCurrencyPrices) { | 592 | case ProfileCurrencyPrices: | ||
1087 | ui->radioButton_bank->setChecked(false); | 593 | ui->m_profilesBank->setChecked(false); | ||
1088 | ui->radioButton_invest->setChecked(false); | 594 | ui->m_profilesInvest->setChecked(false); | ||
1089 | ui->radioButton_stockprices->setChecked(false); | 595 | ui->m_profilesStockPrices->setChecked(false); | ||
1090 | profileTypeStr = "CPrices"; | 596 | break; | ||
1091 | } | 597 | default: | ||
1092 | 598 | break; | |||
1093 | m_wizDlg->m_profileList = profilesGroup.readEntry(profileTypeStr, QStringList()); | 599 | } | ||
1094 | priorProfile = profilesGroup.readEntry("Prior" + profileTypeStr, 0); | 600 | profileTypeStr = CSVImporter::m_profileConfPrefix.value(m_profileType); | ||
1095 | ui->combobox_source->clear(); | 601 | | ||
1096 | ui->combobox_source->addItems(m_wizDlg->m_profileList); | 602 | m_profiles = profilesGroup.readEntry(profileTypeStr, QStringList()); | ||
1097 | ui->combobox_source->setCurrentIndex(priorProfile); | 603 | int priorProfile = profilesGroup.readEntry(CSVImporter::m_confPriorName + profileTypeStr, 0); | ||
1098 | ui->combobox_source->setEnabled(true); | 604 | ui->m_profiles->clear(); | ||
1099 | ui->buttonAdd->setEnabled(true); | 605 | ui->m_profiles->addItems(m_profiles); | ||
606 | ui->m_profiles->setCurrentIndex(priorProfile); | ||||
607 | ui->m_profiles->setEnabled(true); | ||||
608 | ui->m_add->setEnabled(true); | ||||
1100 | } | 609 | } | ||
1101 | 610 | | |||
1102 | void IntroPage::slotBankRadioToggled(bool toggled) | 611 | void IntroPage::slotBankRadioToggled(bool toggled) | ||
1103 | { | 612 | { | ||
1104 | profileTypeChanged(CSVWizard::ProfileBank, toggled); | 613 | profileTypeChanged(ProfileBank, toggled); | ||
1105 | } | 614 | } | ||
1106 | 615 | | |||
1107 | void IntroPage::slotInvestRadioToggled(bool toggled) | 616 | void IntroPage::slotInvestRadioToggled(bool toggled) | ||
1108 | { | 617 | { | ||
1109 | profileTypeChanged(CSVWizard::ProfileInvest, toggled); | 618 | profileTypeChanged(ProfileInvest, toggled); | ||
1110 | } | 619 | } | ||
1111 | 620 | | |||
1112 | void IntroPage::slotCurrencyPricesRadioToggled(bool toggled) | 621 | void IntroPage::slotCurrencyPricesRadioToggled(bool toggled) | ||
1113 | { | 622 | { | ||
1114 | profileTypeChanged(CSVWizard::ProfileCurrencyPrices, toggled); | 623 | profileTypeChanged(ProfileCurrencyPrices, toggled); | ||
1115 | } | 624 | } | ||
1116 | 625 | | |||
1117 | void IntroPage::slotStockPricesRadioToggled(bool toggled) | 626 | void IntroPage::slotStockPricesRadioToggled(bool toggled) | ||
1118 | { | 627 | { | ||
1119 | profileTypeChanged(CSVWizard::ProfileStockPrices, toggled); | 628 | profileTypeChanged(ProfileStockPrices, toggled); | ||
1120 | } | 629 | } | ||
1121 | 630 | | |||
1122 | void IntroPage::initializePage() | 631 | SeparatorPage::SeparatorPage(CSVWizard *dlg, CSVImporter *imp) : | ||
1123 | { | 632 | CSVWizardPage(dlg, imp), | ||
1124 | m_wizDlg->ui->tableWidget->clear(); | | |||
1125 | m_wizDlg->ui->tableWidget->setColumnCount(0); | | |||
1126 | m_wizDlg->ui->tableWidget->setRowCount(0); | | |||
1127 | m_wizDlg->ui->tableWidget->verticalScrollBar()->setValue(0); | | |||
1128 | m_wizDlg->ui->tableWidget->horizontalScrollBar()->setValue(0); | | |||
1129 | | ||||
1130 | wizard()->setButtonText(QWizard::CustomButton1, i18n("Select File")); | | |||
1131 | wizard()->button(QWizard::CustomButton1)->setToolTip(i18n("A profile must be selected before selecting a file.")); | | |||
1132 | QList<QWizard::WizardButton> layout; | | |||
1133 | layout << QWizard::Stretch << | | |||
1134 | QWizard::CustomButton1 << | | |||
1135 | QWizard::CancelButton; | | |||
1136 | wizard()->setButtonLayout(layout); | | |||
1137 | | ||||
1138 | m_wizDlg->m_importError = false; | | |||
1139 | ui->combobox_source->lineEdit()->setClearButtonEnabled(true); | | |||
1140 | | ||||
1141 | connect(ui->combobox_source, SIGNAL(currentIndexChanged(int)), this, SLOT(slotComboSourceIndexChanged(int))); | | |||
1142 | connect(ui->buttonAdd, SIGNAL(clicked()), this, SLOT(slotAddProfile())); | | |||
1143 | connect(ui->buttonRemove, SIGNAL(clicked()), this, SLOT(slotRemoveProfile())); | | |||
1144 | connect(ui->buttonRename, SIGNAL(clicked()), this, SLOT(slotRenameProfile())); | | |||
1145 | connect(ui->radioButton_bank, SIGNAL(toggled(bool)), this, SLOT(slotBankRadioToggled(bool))); | | |||
1146 | connect(ui->radioButton_invest, SIGNAL(toggled(bool)), this, SLOT(slotInvestRadioToggled(bool))); | | |||
1147 | connect(ui->radioButton_currencyprices, SIGNAL(toggled(bool)), this, SLOT(slotCurrencyPricesRadioToggled(bool))); | | |||
1148 | connect(ui->radioButton_stockprices, SIGNAL(toggled(bool)), this, SLOT(slotStockPricesRadioToggled(bool))); | | |||
1149 | if (m_wizDlg->m_initialHeight == -1 || m_wizDlg->m_initialWidth == -1) { | | |||
1150 | m_wizDlg->m_initialHeight = m_wizDlg->geometry().height(); | | |||
1151 | m_wizDlg->m_initialWidth = m_wizDlg->geometry().width(); | | |||
1152 | } else { | | |||
1153 | //resize wizard to its initial size and center it | | |||
1154 | m_wizDlg->setGeometry( | | |||
1155 | QStyle::alignedRect( | | |||
1156 | Qt::LeftToRight, | | |||
1157 | Qt::AlignCenter, | | |||
1158 | QSize(m_wizDlg->m_initialWidth, m_wizDlg->m_initialHeight), | | |||
1159 | QApplication::desktop()->availableGeometry() | | |||
1160 | ) | | |||
1161 | ); | | |||
1162 | } | | |||
1163 | } | | |||
1164 | | ||||
1165 | bool IntroPage::validatePage() | | |||
1166 | { | | |||
1167 | return true; | | |||
1168 | } | | |||
1169 | | ||||
1170 | int IntroPage::nextId() const | | |||
1171 | { | | |||
1172 | return CSVWizard::PageSeparator; | | |||
1173 | } | | |||
1174 | | ||||
1175 | SeparatorPage::SeparatorPage(QDialog *parent) : | | |||
1176 | CSVWizardPage(parent), | | |||
1177 | ui(new Ui::SeparatorPage) | 633 | ui(new Ui::SeparatorPage) | ||
1178 | { | 634 | { | ||
1179 | ui->setupUi(this); | 635 | ui->setupUi(this); | ||
1180 | 636 | | |||
1181 | m_pageLayout = new QVBoxLayout; | 637 | m_pageLayout = new QVBoxLayout; | ||
1182 | ui->horizontalLayout->insertLayout(0, m_pageLayout); | 638 | ui->horizontalLayout->insertLayout(0, m_pageLayout); | ||
1183 | } | 639 | } | ||
1184 | 640 | | |||
1185 | SeparatorPage::~SeparatorPage() | 641 | SeparatorPage::~SeparatorPage() | ||
1186 | { | 642 | { | ||
1187 | delete ui; | 643 | delete ui; | ||
1188 | } | 644 | } | ||
1189 | 645 | | |||
1190 | void SeparatorPage::initializePage() | 646 | void SeparatorPage::initializePage() | ||
1191 | { | 647 | { | ||
1192 | ui->comboBox_fieldDelimiter->setCurrentIndex(m_wizDlg->m_fieldDelimiterIndex); | 648 | // comboboxes are preset to -1 and, in new profile case, can be set here to -1 as well ... | ||
1193 | ui->comboBox_textDelimiter->setCurrentIndex(m_wizDlg->m_textDelimiterIndex); | 649 | initializeEncodingCombobox(); | ||
1194 | connect(ui->comboBox_fieldDelimiter, SIGNAL(currentIndexChanged(int)), this, SLOT(fieldDelimiterChanged(int))); | 650 | ui->m_encoding->setCurrentIndex(ui->m_encoding->findData(m_imp->m_profile->m_encodingMIBEnum)); | ||
1195 | connect(ui->comboBox_textDelimiter, SIGNAL(currentIndexChanged(int)), this, SLOT(textDelimiterChanged(int))); | 651 | ui->m_fieldDelimiter->setCurrentIndex(m_imp->m_profile->m_fieldDelimiterIndex); | ||
1196 | emit ui->comboBox_fieldDelimiter->currentIndexChanged(m_wizDlg->m_fieldDelimiterIndex); | 652 | ui->m_textDelimiter->setCurrentIndex(m_imp->m_profile->m_textDelimiterIndex); | ||
1197 | emit ui->comboBox_textDelimiter->currentIndexChanged(m_wizDlg->m_textDelimiterIndex); | 653 | | ||
654 | // ... so connect their signals after setting them ... | ||||
655 | connect(ui->m_encoding, SIGNAL(currentIndexChanged(int)), this, SLOT(encodingChanged(int))); | ||||
656 | connect(ui->m_fieldDelimiter, SIGNAL(currentIndexChanged(int)), this, SLOT(fieldDelimiterChanged(int))); | ||||
657 | connect(ui->m_textDelimiter, SIGNAL(currentIndexChanged(int)), this, SLOT(textDelimiterChanged(int))); | ||||
658 | | ||||
659 | // ... and ensure that their signal receivers will always be called | ||||
660 | emit ui->m_encoding->currentIndexChanged(ui->m_encoding->currentIndex()); | ||||
661 | emit ui->m_fieldDelimiter->currentIndexChanged(ui->m_fieldDelimiter->currentIndex()); | ||||
662 | emit ui->m_textDelimiter->currentIndexChanged(ui->m_textDelimiter->currentIndex()); | ||||
663 | m_dlg->updateWindowSize(); | ||||
1198 | 664 | | |||
1199 | QList<QWizard::WizardButton> layout; | 665 | QList<QWizard::WizardButton> layout; | ||
1200 | layout << QWizard::Stretch << QWizard::BackButton << QWizard::NextButton << QWizard::CancelButton; | 666 | layout << QWizard::Stretch << QWizard::BackButton << QWizard::NextButton << QWizard::CancelButton; | ||
1201 | wizard()->setButtonLayout(layout); | 667 | wizard()->setButtonLayout(layout); | ||
1202 | } | 668 | } | ||
1203 | 669 | | |||
1204 | void SeparatorPage::textDelimiterChanged(const int index) | 670 | void SeparatorPage::initializeEncodingCombobox() | ||
1205 | { | 671 | { | ||
1206 | if (index < 0) | 672 | ui->m_encoding->blockSignals(true); | ||
1207 | ui->comboBox_textDelimiter->setCurrentIndex(0); // for now there is no better idea how to detect textDelimiter | 673 | ui->m_encoding->clear(); | ||
674 | | ||||
675 | QList<QTextCodec *> codecs; | ||||
676 | QMap<QString, QTextCodec *> codecMap; | ||||
677 | QRegExp iso8859RegExp(QLatin1Literal("ISO[- ]8859-([0-9]+).*")); | ||||
678 | | ||||
679 | foreach (const auto mib, QTextCodec::availableMibs()) { | ||||
680 | QTextCodec *codec = QTextCodec::codecForMib(mib); | ||||
681 | | ||||
682 | QString sortKey = codec->name().toUpper(); | ||||
683 | int rank; | ||||
1208 | 684 | | |||
1209 | m_wizDlg->m_textDelimiterIndex = index; | 685 | if (sortKey.startsWith(QLatin1String("UTF-8"))) { // krazy:exclude=strings | ||
1210 | m_wizDlg->m_parse->setTextDelimiterIndex(index); | 686 | rank = 1; | ||
1211 | m_wizDlg->m_parse->setTextDelimiterCharacter(index); | 687 | } else if (sortKey.startsWith(QLatin1String("UTF-16"))) { // krazy:exclude=strings | ||
1212 | m_wizDlg->m_textDelimiterCharacter = m_wizDlg->m_parse->textDelimiterCharacter(index); | 688 | rank = 2; | ||
689 | } else if (iso8859RegExp.exactMatch(sortKey)) { | ||||
690 | if (iso8859RegExp.cap(1).size() == 1) | ||||
691 | rank = 3; | ||||
692 | else | ||||
693 | rank = 4; | ||||
694 | } else { | ||||
695 | rank = 5; | ||||
696 | } | ||||
697 | sortKey.prepend(QChar('0' + rank)); | ||||
698 | | ||||
699 | codecMap.insert(sortKey, codec); | ||||
700 | } | ||||
701 | codecs = codecMap.values(); | ||||
702 | | ||||
703 | foreach (const auto codec, codecs) | ||||
704 | ui->m_encoding->addItem(codec->name(), codec->mibEnum()); | ||||
705 | ui->m_encoding->blockSignals(false); | ||||
706 | } | ||||
707 | | ||||
708 | void SeparatorPage::encodingChanged(const int index) | ||||
709 | { | ||||
710 | if (index == -1) { | ||||
711 | ui->m_encoding->setCurrentIndex(ui->m_encoding->findText("UTF-8")); | ||||
712 | return; | ||||
713 | } else if (index == ui->m_encoding->findData(m_imp->m_profile->m_encodingMIBEnum)) | ||||
714 | return; | ||||
715 | m_imp->m_profile->m_encodingMIBEnum = ui->m_encoding->currentData().toInt(); | ||||
716 | m_imp->m_file->readFile(m_imp->m_profile); | ||||
717 | emit completeChanged(); | ||||
1213 | } | 718 | } | ||
1214 | 719 | | |||
1215 | void SeparatorPage::fieldDelimiterChanged(const int index) | 720 | void SeparatorPage::fieldDelimiterChanged(const int index) | ||
1216 | { | 721 | { | ||
1217 | if (index == -1 && !m_wizDlg->m_autodetect.value(CSVWizard::AutoFieldDelimiter)) | 722 | if (index == -1 && // if field delimiter isn't set... | ||
723 | !m_imp->m_autodetect.value(AutoFieldDelimiter)) // ... and user disabled autodetecting... | ||||
724 | return; // ... then wait for him to choose | ||||
725 | else if (index == m_imp->m_profile->m_fieldDelimiterIndex) | ||||
1218 | return; | 726 | return; | ||
1219 | m_wizDlg->m_fieldDelimiterIndex = index; | 727 | | ||
1220 | m_wizDlg->m_maxColumnCount = m_wizDlg->getMaxColumnCount(m_wizDlg->m_lineList, m_wizDlg->m_fieldDelimiterIndex); // get column count, we get with this fieldDelimiter | 728 | m_imp->m_profile->m_fieldDelimiterIndex = index; | ||
1221 | m_wizDlg->m_endColumn = m_wizDlg->m_maxColumnCount; | 729 | m_imp->m_file->readFile(m_imp->m_profile); // get column count, we get with this fieldDelimiter | ||
1222 | m_wizDlg->m_parse->setFieldDelimiterIndex(m_wizDlg->m_fieldDelimiterIndex); | 730 | m_imp->m_file->setupParser(m_imp->m_profile); | ||
1223 | m_wizDlg->m_parse->setFieldDelimiterCharacter(m_wizDlg->m_fieldDelimiterIndex); | 731 | | ||
1224 | m_wizDlg->m_fieldDelimiterCharacter = m_wizDlg->m_parse->fieldDelimiterCharacter(m_wizDlg->m_fieldDelimiterIndex); | 732 | if (index == -1) { | ||
733 | ui->m_fieldDelimiter->blockSignals(true); | ||||
734 | ui->m_fieldDelimiter->setCurrentIndex(m_imp->m_profile->m_fieldDelimiterIndex); | ||||
735 | ui->m_fieldDelimiter->blockSignals(false); | ||||
736 | } | ||||
737 | m_dlg->updateWindowSize(); | ||||
738 | emit completeChanged(); | ||||
739 | } | ||||
740 | | ||||
741 | void SeparatorPage::textDelimiterChanged(const int index) | ||||
742 | { | ||||
743 | if (index == -1) { // if text delimiter isn't set... | ||||
744 | ui->m_textDelimiter->setCurrentIndex(0); // ...then set it to 0, as for now there is no better idea how to detect it | ||||
745 | return; | ||||
746 | } | ||||
747 | | ||||
748 | m_imp->m_profile->m_textDelimiterIndex = index; | ||||
749 | m_imp->m_file->setupParser(m_imp->m_profile); | ||||
750 | | ||||
1225 | if (index == -1) { | 751 | if (index == -1) { | ||
1226 | ui->comboBox_fieldDelimiter->blockSignals(true); | 752 | ui->m_textDelimiter->blockSignals(true); | ||
1227 | ui->comboBox_fieldDelimiter->setCurrentIndex(m_wizDlg->m_fieldDelimiterIndex); | 753 | ui->m_textDelimiter->setCurrentIndex(m_imp->m_profile->m_textDelimiterIndex); | ||
1228 | ui->comboBox_fieldDelimiter->blockSignals(false); | 754 | ui->m_textDelimiter->blockSignals(false); | ||
1229 | } | 755 | } | ||
1230 | m_wizDlg->displayLines(m_wizDlg->m_lineList, m_wizDlg->m_parse); // refresh tableWidget with new fieldDelimiter set | | |||
1231 | m_wizDlg->updateWindowSize(); | | |||
1232 | emit completeChanged(); | 756 | emit completeChanged(); | ||
1233 | } | 757 | } | ||
1234 | 758 | | |||
1235 | bool SeparatorPage::isComplete() const | 759 | bool SeparatorPage::isComplete() const | ||
1236 | { | 760 | { | ||
1237 | if (ui->comboBox_fieldDelimiter->currentIndex() != -1) { | 761 | bool rc = false; | ||
1238 | if (m_wizDlg->m_profileType == CSVWizard::ProfileBank && m_wizDlg->m_endColumn > 2) | 762 | if (ui->m_encoding->currentIndex() != -1 && | ||
1239 | return true; | 763 | ui->m_fieldDelimiter->currentIndex() != -1 && | ||
1240 | else if (m_wizDlg->m_profileType == CSVWizard::ProfileInvest && m_wizDlg->m_endColumn > 3) | 764 | ui->m_textDelimiter->currentIndex() != -1) { | ||
1241 | return true; | 765 | switch(m_imp->m_profile->type()) { | ||
1242 | else if ((m_wizDlg->m_profileType == CSVWizard::ProfileStockPrices || | 766 | case ProfileBank: | ||
1243 | m_wizDlg->m_profileType == CSVWizard::ProfileCurrencyPrices) && | 767 | if (m_imp->m_file->m_columnCount > 2) | ||
1244 | m_wizDlg->m_endColumn > 1) | 768 | rc = true; | ||
1245 | return true; | 769 | break; | ||
770 | case ProfileInvest: | ||||
771 | if (m_imp->m_file->m_columnCount > 3) | ||||
772 | rc = true; | ||||
773 | break; | ||||
774 | case ProfileCurrencyPrices: | ||||
775 | case ProfileStockPrices: | ||||
776 | if (m_imp->m_file->m_columnCount > 1) | ||||
777 | rc = true; | ||||
778 | break; | ||||
779 | default: | ||||
780 | break; | ||||
1246 | } | 781 | } | ||
1247 | return false; | 782 | } | ||
783 | return rc; | ||||
1248 | } | 784 | } | ||
1249 | 785 | | |||
1250 | bool SeparatorPage::validatePage() | 786 | bool SeparatorPage::validatePage() | ||
1251 | { | 787 | { | ||
1252 | return true; | 788 | return true; | ||
1253 | } | 789 | } | ||
1254 | 790 | | |||
1255 | void SeparatorPage::cleanupPage() | 791 | void SeparatorPage::cleanupPage() | ||
1256 | { | 792 | { | ||
1257 | // On completion with error force use of 'Back' button. | 793 | // On completion with error force use of 'Back' button. | ||
1258 | // ...to allow resetting of 'Skip setup' | 794 | // ...to allow resetting of 'Skip setup' | ||
1259 | disconnect(ui->comboBox_fieldDelimiter, SIGNAL(currentIndexChanged(int)), this, SLOT(fieldDelimiterChanged(int))); | 795 | disconnect(ui->m_fieldDelimiter, SIGNAL(currentIndexChanged(int)), this, SLOT(fieldDelimiterChanged(int))); | ||
1260 | disconnect(ui->comboBox_textDelimiter, SIGNAL(currentIndexChanged(int)), this, SLOT(textDelimiterChanged(int))); | 796 | disconnect(ui->m_textDelimiter, SIGNAL(currentIndexChanged(int)), this, SLOT(textDelimiterChanged(int))); | ||
1261 | m_wizDlg->m_pageIntro->initializePage(); // Need to show button(QWizard::CustomButton1) not 'NextButton' | 797 | m_dlg->m_pageIntro->initializePage(); // Need to show button(QWizard::CustomButton1) not 'NextButton' | ||
1262 | } | 798 | } | ||
1263 | 799 | | |||
1264 | RowsPage::RowsPage(QDialog *parent) : | 800 | RowsPage::RowsPage(CSVWizard *dlg, CSVImporter *imp) : | ||
1265 | CSVWizardPage(parent), | 801 | CSVWizardPage(dlg, imp), | ||
1266 | ui(new Ui::RowsPage) | 802 | ui(new Ui::RowsPage) | ||
1267 | { | 803 | { | ||
1268 | ui->setupUi(this); | 804 | ui->setupUi(this); | ||
1269 | m_pageLayout = new QVBoxLayout; | 805 | m_pageLayout = new QVBoxLayout; | ||
1270 | ui->horizontalLayout->insertLayout(0, m_pageLayout); | 806 | ui->horizontalLayout->insertLayout(0, m_pageLayout); | ||
1271 | } | 807 | } | ||
1272 | 808 | | |||
1273 | RowsPage::~RowsPage() | 809 | RowsPage::~RowsPage() | ||
1274 | { | 810 | { | ||
1275 | delete ui; | 811 | delete ui; | ||
1276 | } | 812 | } | ||
1277 | 813 | | |||
1278 | void RowsPage::initializePage() | 814 | void RowsPage::initializePage() | ||
1279 | { | 815 | { | ||
1280 | disconnect(ui->spinBox_skip, SIGNAL(valueChanged(int)), this, SLOT(startRowChanged(int))); | 816 | // disconnect(ui->m_startLine, &QSpinBox::valueChanged, this, &RowsPage::startRowChanged); | ||
1281 | disconnect(ui->spinBox_skipToLast, SIGNAL(valueChanged(int)), this, SLOT(endRowChanged(int))); | 817 | // disconnect(ui->m_endLine, &QSpinBox::valueChanged, this, &RowsPage::endRowChanged); | ||
1282 | 818 | | |||
1283 | ui->spinBox_skip->setMaximum(m_wizDlg->m_fileEndLine); | 819 | ui->m_startLine->setMaximum(m_imp->m_file->m_rowCount); | ||
1284 | ui->spinBox_skipToLast->setMaximum(m_wizDlg->m_fileEndLine); | 820 | ui->m_endLine->setMaximum(m_imp->m_file->m_rowCount); | ||
1285 | ui->spinBox_skip->setValue(m_wizDlg->m_startLine); | 821 | ui->m_startLine->setValue(m_imp->m_profile->m_startLine + 1); | ||
1286 | ui->spinBox_skipToLast->setValue(m_wizDlg->m_endLine); | 822 | ui->m_endLine->setValue(m_imp->m_profile->m_endLine + 1); | ||
1287 | 823 | | |||
1288 | m_wizDlg->markUnwantedRows(); | 824 | m_dlg->markUnwantedRows(); | ||
1289 | m_wizDlg->m_vScrollBar->setValue(m_wizDlg->m_startLine - 1); | 825 | m_dlg->m_vScrollBar->setValue(m_imp->m_profile->m_startLine); | ||
1290 | 826 | | |||
1291 | connect(ui->spinBox_skip, SIGNAL(valueChanged(int)), this, SLOT(startRowChanged(int))); | 827 | connect(ui->m_startLine, SIGNAL(valueChanged(int)), this, SLOT(startRowChanged(int)));; | ||
1292 | connect(ui->spinBox_skipToLast, SIGNAL(valueChanged(int)), this, SLOT(endRowChanged(int))); | 828 | connect(ui->m_endLine, SIGNAL(valueChanged(int)), this, SLOT(endRowChanged(int))); | ||
1293 | 829 | | |||
1294 | QList<QWizard::WizardButton> layout; | 830 | QList<QWizard::WizardButton> layout; | ||
1295 | layout << QWizard::Stretch << | 831 | layout << QWizard::Stretch << | ||
1296 | QWizard::BackButton << | 832 | QWizard::BackButton << | ||
1297 | QWizard::NextButton << | 833 | QWizard::NextButton << | ||
1298 | QWizard::CancelButton; | 834 | QWizard::CancelButton; | ||
1299 | wizard()->setButtonLayout(layout); | 835 | wizard()->setButtonLayout(layout); | ||
1300 | } | 836 | } | ||
1301 | 837 | | |||
838 | void RowsPage::cleanupPage() | ||||
839 | { | ||||
840 | disconnect(ui->m_startLine, SIGNAL(valueChanged(int)), this, SLOT(startRowChanged(int)));; | ||||
841 | disconnect(ui->m_endLine, SIGNAL(valueChanged(int)), this, SLOT(endRowChanged(int))); | ||||
842 | m_dlg->clearBackground(); | ||||
843 | } | ||||
844 | | ||||
845 | int RowsPage::nextId() const | ||||
846 | { | ||||
847 | int ret; | ||||
848 | switch (m_imp->m_profile->type()) { | ||||
849 | case ProfileBank: | ||||
850 | ret = CSVWizard::PageBanking; | ||||
851 | break; | ||||
852 | case ProfileInvest: | ||||
853 | ret = CSVWizard::PageInvestment; | ||||
854 | break; | ||||
855 | case ProfileStockPrices: | ||||
856 | case ProfileCurrencyPrices: | ||||
857 | ret = CSVWizard::PagePrices; | ||||
858 | break; | ||||
859 | default: | ||||
860 | ret = CSVWizard::PageRows; | ||||
861 | break; | ||||
862 | } | ||||
863 | return ret; | ||||
864 | } | ||||
865 | | ||||
1302 | void RowsPage::startRowChanged(int val) | 866 | void RowsPage::startRowChanged(int val) | ||
1303 | { | 867 | { | ||
1304 | if (val > m_wizDlg->m_fileEndLine) { | 868 | if (val > m_imp->m_file->m_rowCount) { | ||
1305 | ui->spinBox_skip->setValue(m_wizDlg->m_fileEndLine); | 869 | ui->m_startLine->setValue(m_imp->m_file->m_rowCount); | ||
1306 | return; | 870 | return; | ||
1307 | } | 871 | } | ||
1308 | if (val > m_wizDlg->m_endLine) { | 872 | --val; | ||
1309 | ui->spinBox_skip->setValue(m_wizDlg->m_endLine); | 873 | if (val > m_imp->m_profile->m_endLine) { | ||
874 | ui->m_startLine->setValue(m_imp->m_profile->m_endLine); | ||||
1310 | return; | 875 | return; | ||
1311 | } | 876 | } | ||
1312 | m_wizDlg->m_startLine = val; | 877 | m_imp->m_profile->m_startLine = val; | ||
1313 | if (!m_wizDlg->m_inFileName.isEmpty()) { | 878 | m_dlg->m_vScrollBar->setValue(val); | ||
1314 | m_wizDlg->m_vScrollBar->setValue(m_wizDlg->m_startLine - 1); | 879 | m_dlg->markUnwantedRows(); | ||
1315 | m_wizDlg->markUnwantedRows(); | | |||
1316 | } | | |||
1317 | } | 880 | } | ||
1318 | 881 | | |||
1319 | void RowsPage::endRowChanged(int val) | 882 | void RowsPage::endRowChanged(int val) | ||
1320 | { | 883 | { | ||
1321 | if (val > m_wizDlg->m_fileEndLine) { | 884 | if (val > m_imp->m_file->m_rowCount) { | ||
1322 | ui->spinBox_skipToLast->setValue(m_wizDlg->m_fileEndLine); | 885 | ui->m_endLine->setValue(m_imp->m_file->m_rowCount); | ||
1323 | return; | 886 | return; | ||
1324 | } | 887 | } | ||
1325 | if (val < m_wizDlg->m_startLine) { | 888 | --val; | ||
1326 | ui->spinBox_skipToLast->setValue(m_wizDlg->m_startLine); | 889 | if (val < m_imp->m_profile->m_startLine) { | ||
890 | ui->m_endLine->setValue(m_imp->m_profile->m_startLine); | ||||
1327 | return; | 891 | return; | ||
1328 | } | 892 | } | ||
1329 | m_wizDlg->m_trailerLines = m_wizDlg->m_fileEndLine - val; | 893 | m_imp->m_profile->m_trailerLines = m_imp->m_file->m_rowCount - val; | ||
1330 | m_wizDlg->m_endLine = val; | 894 | m_imp->m_profile->m_endLine = val; | ||
1331 | if (!m_wizDlg->m_inFileName.isEmpty()) { | 895 | m_dlg->markUnwantedRows(); | ||
1332 | m_wizDlg->markUnwantedRows(); | | |||
1333 | } | | |||
1334 | } | 896 | } | ||
1335 | 897 | | |||
1336 | void RowsPage::cleanupPage() | | |||
1337 | { | | |||
1338 | disconnect(ui->spinBox_skip, SIGNAL(valueChanged(int)), this, SLOT(startRowChanged(int))); | | |||
1339 | disconnect(ui->spinBox_skipToLast, SIGNAL(valueChanged(int)), this, SLOT(endRowChanged(int))); | | |||
1340 | m_wizDlg->clearBackground(); | | |||
1341 | } | | |||
1342 | 898 | | |||
1343 | int RowsPage::nextId() const | | |||
1344 | { | | |||
1345 | int ret = CSVWizard::PageBanking; | | |||
1346 | if (m_wizDlg->m_profileType == CSVWizard::ProfileBank) | | |||
1347 | ret = CSVWizard::PageBanking; | | |||
1348 | else if (m_wizDlg->m_profileType == CSVWizard::ProfileInvest) | | |||
1349 | ret = CSVWizard::PageInvestment; | | |||
1350 | else if (m_wizDlg->m_profileType == CSVWizard::ProfileStockPrices || | | |||
1351 | m_wizDlg->m_profileType == CSVWizard::ProfileCurrencyPrices) | | |||
1352 | ret = CSVWizard::PagePrices; | | |||
1353 | return ret; | | |||
1354 | } | | |||
1355 | 899 | | |||
1356 | FormatsPage::FormatsPage(QDialog *parent) : | 900 | | ||
1357 | CSVWizardPage(parent), | 901 | | ||
902 | FormatsPage::FormatsPage(CSVWizard *dlg, CSVImporter *imp) : | ||||
903 | CSVWizardPage(dlg, imp), | ||||
1358 | ui(new Ui::FormatsPage) | 904 | ui(new Ui::FormatsPage) | ||
1359 | { | 905 | { | ||
1360 | ui->setupUi(this); | 906 | ui->setupUi(this); | ||
1361 | m_pageLayout = new QVBoxLayout; | 907 | m_pageLayout = new QVBoxLayout; | ||
1362 | ui->horizontalLayout->insertLayout(0, m_pageLayout); | 908 | ui->horizontalLayout->insertLayout(0, m_pageLayout); | ||
1363 | } | 909 | } | ||
1364 | 910 | | |||
1365 | FormatsPage::~FormatsPage() | 911 | FormatsPage::~FormatsPage() | ||
Show All 20 Lines | 917 | { | |||
1386 | wizard()->setButtonText(QWizard::CustomButton3, i18n("Make QIF File")); | 932 | wizard()->setButtonText(QWizard::CustomButton3, i18n("Make QIF File")); | ||
1387 | wizard()->setButtonLayout(layout); | 933 | wizard()->setButtonLayout(layout); | ||
1388 | wizard()->button(QWizard::CustomButton2)->setEnabled(false); | 934 | wizard()->button(QWizard::CustomButton2)->setEnabled(false); | ||
1389 | wizard()->button(QWizard::CustomButton3)->setEnabled(false); | 935 | wizard()->button(QWizard::CustomButton3)->setEnabled(false); | ||
1390 | wizard()->button(QWizard::FinishButton)->setEnabled(false); | 936 | wizard()->button(QWizard::FinishButton)->setEnabled(false); | ||
1391 | 937 | | |||
1392 | ui->comboBox_thousandsDelimiter->setEnabled(false); | 938 | ui->comboBox_thousandsDelimiter->setEnabled(false); | ||
1393 | 939 | | |||
1394 | ui->comboBox_dateFormat->setCurrentIndex(m_wizDlg->m_dateFormatIndex); // put before connect to not emit update signal | 940 | ui->comboBox_dateFormat->setCurrentIndex(m_imp->m_profile->m_dateFormatIndex); // put before connect to not emit update signal | ||
1395 | connect(ui->comboBox_dateFormat, SIGNAL(currentIndexChanged(int)), this, SLOT(dateFormatChanged(int))); | 941 | connect(ui->comboBox_dateFormat, SIGNAL(currentIndexChanged(int)), this, SLOT(dateFormatChanged(int))); | ||
1396 | emit ui->comboBox_dateFormat->currentIndexChanged(m_wizDlg->m_dateFormatIndex); // emit update signal manually regardless of change to combobox | 942 | emit ui->comboBox_dateFormat->currentIndexChanged(m_imp->m_profile->m_dateFormatIndex); // emit update signal manually regardless of change to combobox | ||
1397 | 943 | | |||
1398 | ui->comboBox_decimalSymbol->setCurrentIndex(m_wizDlg->m_decimalSymbolIndex); // put before connect to not emit update signal | 944 | ui->comboBox_decimalSymbol->setCurrentIndex(m_imp->m_profile->m_decimalSymbolIndex); // put before connect to not emit update signal | ||
1399 | connect(ui->comboBox_decimalSymbol, SIGNAL(currentIndexChanged(int)), this, SLOT(decimalSymbolChanged(int))); | 945 | connect(ui->comboBox_decimalSymbol, SIGNAL(currentIndexChanged(int)), this, SLOT(decimalSymbolChanged(int))); | ||
1400 | emit ui->comboBox_decimalSymbol->currentIndexChanged(m_wizDlg->m_decimalSymbolIndex); // emit update signal manually regardless of change to combobox | 946 | emit ui->comboBox_decimalSymbol->currentIndexChanged(m_imp->m_profile->m_decimalSymbolIndex); // emit update signal manually regardless of change to combobox | ||
1401 | 947 | | |||
1402 | if (m_wizDlg->m_skipSetup && | 948 | if (m_dlg->m_skipSetup && | ||
1403 | wizard()->button(QWizard::CustomButton2)->isEnabled()) | 949 | wizard()->button(QWizard::CustomButton2)->isEnabled()) | ||
1404 | slotImportClicked(); | 950 | m_dlg->importClicked(); | ||
1405 | } | 951 | } | ||
1406 | 952 | | |||
1407 | void FormatsPage::decimalSymbolChanged(int index) | 953 | void FormatsPage::decimalSymbolChanged(int index) | ||
1408 | { | 954 | { | ||
955 | QList<int> columns = m_imp->getNumericalColumns(); | ||||
1409 | switch (index) { | 956 | switch (index) { | ||
1410 | case -1: | 957 | case -1: | ||
1411 | if (!m_wizDlg->m_autodetect.value(CSVWizard::AutoDecimalSymbol)) | 958 | if (!m_imp->m_autodetect.value(AutoDecimalSymbol)) | ||
1412 | return; | | |||
1413 | case 2: | | |||
1414 | m_wizDlg->m_decimalSymbolIndex = 2; | | |||
1415 | m_wizDlg->m_decimalSymbol.clear(); | | |||
1416 | break; | 959 | break; | ||
1417 | default: | 960 | case 2: | ||
1418 | m_wizDlg->m_parse->setDecimalSymbol(index); | 961 | { | ||
1419 | m_wizDlg->m_parse->setDecimalSymbolIndex(index); | | |||
1420 | m_wizDlg->m_parse->setThousandsSeparator(index); | | |||
1421 | m_wizDlg->m_parse->setThousandsSeparatorIndex(index); | | |||
1422 | | ||||
1423 | m_wizDlg->m_decimalSymbol = m_wizDlg->m_parse->decimalSymbol(index); | | |||
1424 | m_wizDlg->m_decimalSymbolIndex = m_wizDlg->m_parse->decimalSymbolIndex(); | | |||
1425 | } | | |||
1426 | ui->comboBox_thousandsDelimiter->setCurrentIndex(m_wizDlg->m_decimalSymbolIndex); | | |||
1427 | | ||||
1428 | bool isOk = true; | | |||
1429 | QList<int> columnList; | | |||
1430 | if (m_wizDlg->m_profileType == CSVWizard::ProfileBank) { | | |||
1431 | if (m_wizDlg->m_pageBanking->m_colTypeNum.value(BankingPage::ColumnAmount) >= 0) { | | |||
1432 | columnList << m_wizDlg->m_pageBanking->m_colTypeNum.value(BankingPage::ColumnAmount); | | |||
1433 | } else { | | |||
1434 | columnList << m_wizDlg->m_pageBanking->m_colTypeNum.value(BankingPage::ColumnDebit); | | |||
1435 | columnList << m_wizDlg->m_pageBanking->m_colTypeNum.value(BankingPage::ColumnCredit); | | |||
1436 | } | | |||
1437 | } else if (m_wizDlg->m_profileType == CSVWizard::ProfileInvest) { | | |||
1438 | columnList << m_wizDlg->m_pageInvestment->m_colTypeNum.value(InvestmentPage::ColumnAmount); | | |||
1439 | columnList << m_wizDlg->m_pageInvestment->m_colTypeNum.value(InvestmentPage::ColumnPrice); | | |||
1440 | columnList << m_wizDlg->m_pageInvestment->m_colTypeNum.value(InvestmentPage::ColumnQuantity); | | |||
1441 | if (m_wizDlg->m_pageInvestment->m_colTypeNum.value(InvestmentPage::ColumnFee) != -1) | | |||
1442 | columnList << m_wizDlg->m_pageInvestment->m_colTypeNum.value(InvestmentPage::ColumnFee); | | |||
1443 | } else if (m_wizDlg->m_profileType == CSVWizard::ProfileStockPrices || | | |||
1444 | m_wizDlg->m_profileType == CSVWizard::ProfileCurrencyPrices) { | | |||
1445 | columnList << m_wizDlg->m_pagePrices->m_colTypeNum.value(PricesPage::ColumnPrice); | | |||
1446 | } | | |||
1447 | | ||||
1448 | for (QList<int>::const_iterator col = columnList.constBegin(); col < columnList.constEnd(); ++col) { | | |||
1449 | int detectedSymbol = m_wizDlg->m_decimalSymbolIndex; | | |||
1450 | if (!m_wizDlg->detectDecimalSymbol(*col, detectedSymbol)) { | | |||
1451 | isOk = false; | | |||
1452 | KMessageBox::sorry(this, i18n("<center>Autodetect could not detect your decimal symbol in column %1.</center>" | | |||
1453 | "<center>Try manual selection to see problematic cells and correct your data.</center>", *col + 1), i18n("CSV import")); | | |||
1454 | ui->comboBox_decimalSymbol->blockSignals(true); | 962 | ui->comboBox_decimalSymbol->blockSignals(true); | ||
963 | m_imp->m_profile->m_decimalSymbolIndex = 2; | ||||
964 | int failColumn = m_imp->detectDecimalSymbols(columns); | ||||
965 | if (failColumn != -2) { | ||||
966 | KMessageBox::sorry(this, i18n("<center>Autodetect could not detect your decimal symbol in column %1.</center>" | ||||
967 | "<center>Try manual selection to see problematic cells and correct your data.</center>", failColumn), i18n("CSV import")); | ||||
1455 | ui->comboBox_decimalSymbol->setCurrentIndex(-1); | 968 | ui->comboBox_decimalSymbol->setCurrentIndex(-1); | ||
1456 | ui->comboBox_decimalSymbol->blockSignals(false); | | |||
1457 | ui->comboBox_thousandsDelimiter->setCurrentIndex(-1); | 969 | ui->comboBox_thousandsDelimiter->setCurrentIndex(-1); | ||
1458 | break; | 970 | } else if (index == -1) { // if detection went well and decimal symbol was unspecified then we'll be specifying it | ||
1459 | } | 971 | int firstDecSymbol = m_imp->m_decimalSymbolIndexMap.first(); | ||
1460 | m_wizDlg->m_decimalSymbolIndexMap.insert(*col, detectedSymbol); | | |||
1461 | m_wizDlg->m_parse->setDecimalSymbol(detectedSymbol); | | |||
1462 | m_wizDlg->m_parse->setThousandsSeparator(detectedSymbol); // separator list is in reverse so it's ok | | |||
1463 | | ||||
1464 | isOk &= validateDecimalSymbol(*col); | | |||
1465 | } | | |||
1466 | | ||||
1467 | if (index == -1 && isOk) { // if detection went well and decimal symbol was unspeciffied then we'll be specifying it | | |||
1468 | int prevDecimalSymbol = columnList.value(0); | | |||
1469 | bool allSymbolsEqual = true; | 972 | bool allSymbolsEqual = true; | ||
1470 | for (QList<int>::const_iterator col = columnList.constBegin(); col < columnList.constEnd(); ++col) { | 973 | foreach (const auto mapDecSymbol, m_imp->m_decimalSymbolIndexMap) { | ||
1471 | if (m_wizDlg->m_decimalSymbolIndexMap.value(*col) != prevDecimalSymbol) | 974 | if (firstDecSymbol != mapDecSymbol) | ||
1472 | allSymbolsEqual = false; | 975 | allSymbolsEqual = false; | ||
1473 | } | 976 | } | ||
1474 | ui->comboBox_decimalSymbol->blockSignals(true); | | |||
1475 | if (allSymbolsEqual) { // if symbol in all columns is equal then set it... | 977 | if (allSymbolsEqual) { // if symbol in all columns is equal then set it... | ||
1476 | ui->comboBox_decimalSymbol->setCurrentIndex(prevDecimalSymbol); | 978 | m_imp->m_profile->m_decimalSymbolIndex = firstDecSymbol; | ||
1477 | ui->comboBox_thousandsDelimiter->setCurrentIndex(prevDecimalSymbol); | 979 | ui->comboBox_decimalSymbol->setCurrentIndex(firstDecSymbol); | ||
980 | ui->comboBox_thousandsDelimiter->setCurrentIndex(firstDecSymbol); | ||||
1478 | } else { // else set to auto | 981 | } else { // else set to auto | ||
982 | m_imp->m_profile->m_decimalSymbolIndex = 2; | ||||
1479 | ui->comboBox_decimalSymbol->setCurrentIndex(2); | 983 | ui->comboBox_decimalSymbol->setCurrentIndex(2); | ||
1480 | ui->comboBox_thousandsDelimiter->setCurrentIndex(2); | 984 | ui->comboBox_thousandsDelimiter->setCurrentIndex(2); | ||
1481 | } | 985 | } | ||
986 | } | ||||
1482 | ui->comboBox_decimalSymbol->blockSignals(false); | 987 | ui->comboBox_decimalSymbol->blockSignals(false); | ||
988 | break; | ||||
989 | } | ||||
990 | default: | ||||
991 | foreach (const auto column, columns) | ||||
992 | m_imp->m_decimalSymbolIndexMap.insert(column, index); | ||||
993 | ui->comboBox_thousandsDelimiter->setCurrentIndex(index); | ||||
994 | m_imp->m_profile->m_decimalSymbolIndex = index; | ||||
1483 | } | 995 | } | ||
1484 | 996 | | |||
1485 | m_isDecimalSymbolOK = isOk; | 997 | m_isDecimalSymbolOK = validateDecimalSymbols(columns); | ||
1486 | emit completeChanged(); | 998 | emit completeChanged(); | ||
1487 | } | 999 | } | ||
1488 | 1000 | | |||
1489 | bool FormatsPage::validateDecimalSymbol(int col) | 1001 | bool FormatsPage::validateDecimalSymbols(const QList<int> &columns) | ||
1490 | { | 1002 | { | ||
1491 | m_wizDlg->clearColumnsBackground(col); | | |||
1492 | | ||||
1493 | bool isOK = true; | 1003 | bool isOK = true; | ||
1494 | for (int row = m_wizDlg->m_startLine - 1; row < m_wizDlg->m_endLine; ++row) { | 1004 | foreach (const auto col, columns) { | ||
1495 | QTableWidgetItem* item = m_wizDlg->ui->tableWidget->item(row, col); | 1005 | m_imp->m_file->m_parse->setDecimalSymbol(m_imp->m_decimalSymbolIndexMap.value(col)); | ||
1006 | m_imp->m_file->m_parse->setThousandsSeparator(m_imp->m_decimalSymbolIndexMap.value(col)); | ||||
1007 | m_dlg->clearColumnsBackground(col); | ||||
1008 | for (int row = m_imp->m_profile->m_startLine; row <= m_imp->m_profile->m_endLine; ++row) { | ||||
1009 | QStandardItem *item = m_imp->m_file->m_model->item(row, col); | ||||
1496 | QString rawNumber = item->text(); | 1010 | QString rawNumber = item->text(); | ||
1497 | m_wizDlg->m_parse->possiblyReplaceSymbol(rawNumber); | 1011 | m_imp->m_file->m_parse->possiblyReplaceSymbol(rawNumber); | ||
1498 | 1012 | if (!m_imp->m_file->m_parse->invalidConversion() || | |||
1499 | if (!m_wizDlg->m_parse->invalidConversion() || | | |||
1500 | rawNumber.isEmpty()) { // empty strings are welcome | 1013 | rawNumber.isEmpty()) { // empty strings are welcome | ||
1501 | item->setBackground(m_wizDlg->m_colorBrush); | 1014 | item->setBackground(m_dlg->m_colorBrush); | ||
1502 | item->setForeground(m_wizDlg->m_colorBrushText); | 1015 | item->setForeground(m_dlg->m_colorBrushText); | ||
1503 | } else { | 1016 | } else { | ||
1504 | isOK = false; | 1017 | isOK = false; | ||
1505 | m_wizDlg->ui->tableWidget->scrollToItem(item, QAbstractItemView::EnsureVisible); | 1018 | m_dlg->ui->tableView->scrollTo(item->index(), QAbstractItemView::EnsureVisible); | ||
1506 | item->setBackground(m_wizDlg->m_errorBrush); | 1019 | item->setBackground(m_dlg->m_errorBrush); | ||
1507 | item->setForeground(m_wizDlg->m_errorBrushText); | 1020 | item->setForeground(m_dlg->m_errorBrushText); | ||
1508 | } | 1021 | } | ||
1509 | } | 1022 | } | ||
1023 | | ||||
1024 | } | ||||
1510 | return isOK; | 1025 | return isOK; | ||
1511 | } | 1026 | } | ||
1512 | 1027 | | |||
1513 | void FormatsPage::dateFormatChanged(int index) | 1028 | void FormatsPage::dateFormatChanged(const int index) | ||
1514 | { | 1029 | { | ||
1515 | if (index < 0) | 1030 | if (index == -1) | ||
1516 | return; | 1031 | return; | ||
1517 | else { | | |||
1518 | m_wizDlg->m_dateFormatIndex = index; | | |||
1519 | m_wizDlg->m_date = m_wizDlg->m_dateFormats[m_wizDlg->m_dateFormatIndex]; | | |||
1520 | } | | |||
1521 | 1032 | | |||
1522 | int col = 0; | 1033 | int col = m_imp->m_profile->m_colTypeNum.value(ColumnDate); | ||
1523 | if (m_wizDlg->m_profileType == CSVWizard::ProfileBank) | 1034 | m_imp->m_profile->m_dateFormatIndex = index; | ||
1524 | col = m_wizDlg->m_pageBanking->m_colTypeNum.value(BankingPage::ColumnDate); | 1035 | m_imp->m_convertDate->setDateFormatIndex(index); | ||
1525 | else if (m_wizDlg->m_profileType == CSVWizard::ProfileInvest) | | |||
1526 | col = m_wizDlg->m_pageInvestment->m_colTypeNum.value(InvestmentPage::ColumnDate); | | |||
1527 | else if (m_wizDlg->m_profileType == CSVWizard::ProfileStockPrices || | | |||
1528 | m_wizDlg->m_profileType == CSVWizard::ProfileCurrencyPrices) | | |||
1529 | col = m_wizDlg->m_pagePrices->m_colTypeNum.value(PricesPage::ColumnDate); | | |||
1530 | | ||||
1531 | m_wizDlg->m_convertDate->setDateFormatIndex(index); | | |||
1532 | m_isDateFormatOK = validateDateFormat(col); | 1036 | m_isDateFormatOK = validateDateFormat(col); | ||
1533 | if (!m_isDateFormatOK) { | 1037 | if (!m_isDateFormatOK) { | ||
1534 | KMessageBox::sorry(this, i18n("<center>There are invalid date formats in column '%1'.</center>" | 1038 | KMessageBox::sorry(this, i18n("<center>There are invalid date formats in column '%1'.</center>" | ||
1535 | "<center>Please check your selections.</center>" | 1039 | "<center>Please check your selections.</center>" | ||
1536 | , col + 1), i18n("CSV import")); | 1040 | , col + 1), i18n("CSV import")); | ||
1537 | } | 1041 | } | ||
1538 | emit completeChanged(); | 1042 | emit completeChanged(); | ||
1539 | } | 1043 | } | ||
1540 | 1044 | | |||
1541 | bool FormatsPage::validateDateFormat(int col) | 1045 | bool FormatsPage::validateDateFormat(const int col) | ||
1542 | { | 1046 | { | ||
1543 | m_wizDlg->clearColumnsBackground(col); | 1047 | m_dlg->clearColumnsBackground(col); | ||
1544 | 1048 | | |||
1545 | bool isOK = true; | 1049 | bool isOK = true; | ||
1546 | for (int row = m_wizDlg->m_startLine - 1; row < m_wizDlg->m_endLine; ++row) { | 1050 | for (int row = m_imp->m_profile->m_startLine; row <= m_imp->m_profile->m_endLine; ++row) { | ||
1547 | QTableWidgetItem* item = m_wizDlg->ui->tableWidget->item(row, col); | 1051 | QStandardItem* item = m_imp->m_file->m_model->item(row, col); | ||
1548 | 1052 | QDate dat = m_imp->m_convertDate->convertDate(item->text()); | |||
1549 | QDate dat = m_wizDlg->m_convertDate->convertDate(item->text()); | | |||
1550 | | ||||
1551 | if (dat == QDate()) { | 1053 | if (dat == QDate()) { | ||
1552 | isOK = false; | 1054 | isOK = false; | ||
1553 | m_wizDlg->ui->tableWidget->scrollToItem(item, QAbstractItemView::EnsureVisible); | 1055 | m_dlg->ui->tableView->scrollTo(item->index(), QAbstractItemView::EnsureVisible); | ||
1554 | item->setBackground(m_wizDlg->m_errorBrush); | 1056 | item->setBackground(m_dlg->m_errorBrush); | ||
1555 | item->setForeground(m_wizDlg->m_errorBrushText); | 1057 | item->setForeground(m_dlg->m_errorBrushText); | ||
1556 | } else { | 1058 | } else { | ||
1557 | item->setBackground(m_wizDlg->m_colorBrush); | 1059 | item->setBackground(m_dlg->m_colorBrush); | ||
1558 | item->setForeground(m_wizDlg->m_colorBrushText); | 1060 | item->setForeground(m_dlg->m_colorBrushText); | ||
1559 | } | 1061 | } | ||
1560 | } | 1062 | } | ||
1561 | return isOK; | 1063 | return isOK; | ||
1562 | } | 1064 | } | ||
1563 | 1065 | | |||
1564 | void FormatsPage::slotImportClicked() | | |||
1565 | { | | |||
1566 | bool isOK = true; | | |||
1567 | if (m_wizDlg->m_profileType == CSVWizard::ProfileBank) | | |||
1568 | isOK = m_wizDlg->m_pageBanking->createStatement(m_wizDlg->st); | | |||
1569 | else if (m_wizDlg->m_profileType == CSVWizard::ProfileInvest) | | |||
1570 | isOK = m_wizDlg->m_pageInvestment->createStatement(m_wizDlg->st); | | |||
1571 | else if (m_wizDlg->m_profileType == CSVWizard::ProfileStockPrices || | | |||
1572 | m_wizDlg->m_profileType == CSVWizard::ProfileCurrencyPrices) | | |||
1573 | isOK = m_wizDlg->m_pagePrices->createStatement(m_wizDlg->st); | | |||
1574 | | ||||
1575 | if (!isOK) { | | |||
1576 | m_wizDlg->st = MyMoneyStatement(); // statement is invalid so erase it | | |||
1577 | return; | | |||
1578 | } | | |||
1579 | | ||||
1580 | m_wizDlg->hide(); //hide wizard so it will not cover accountselector | | |||
1581 | emit m_wizDlg->statementReady(m_wizDlg->st); | | |||
1582 | m_wizDlg->slotClose(); //close hidden window as it isn't needed anymore | | |||
1583 | } | | |||
1584 | | ||||
1585 | void FormatsPage::slotSaveAsQIFClicked() | | |||
1586 | { | | |||
1587 | bool isOK = true; | | |||
1588 | if (m_wizDlg->m_profileType == CSVWizard::ProfileBank) | | |||
1589 | isOK = m_wizDlg->m_pageBanking->createStatement(m_wizDlg->st); | | |||
1590 | else if (m_wizDlg->m_profileType == CSVWizard::ProfileInvest) | | |||
1591 | isOK = m_wizDlg->m_pageInvestment->createStatement(m_wizDlg->st); | | |||
1592 | | ||||
1593 | if (!isOK || m_wizDlg->st.m_listTransactions.isEmpty()) | | |||
1594 | return; | | |||
1595 | | ||||
1596 | QString outFileName = m_wizDlg->m_inFileName; | | |||
1597 | outFileName.truncate(m_wizDlg->m_inFileName.lastIndexOf('.')); | | |||
1598 | outFileName += ".qif"; | | |||
1599 | outFileName = QFileDialog::getSaveFileName(this, i18n("Save QIF"), outFileName, i18n("QIF Files (*.qif)")); | | |||
1600 | if (outFileName.isEmpty()) | | |||
1601 | return; | | |||
1602 | QFile oFile(outFileName); | | |||
1603 | oFile.open(QIODevice::WriteOnly); | | |||
1604 | if (m_wizDlg->m_profileType == CSVWizard::ProfileBank) | | |||
1605 | m_wizDlg->m_pageBanking->makeQIF(m_wizDlg->st, oFile); | | |||
1606 | else if (m_wizDlg->m_profileType == CSVWizard::ProfileInvest) | | |||
1607 | m_wizDlg->m_pageInvestment->makeQIF(m_wizDlg->st, oFile); | | |||
1608 | oFile.close(); | | |||
1609 | } | | |||
1610 | | ||||
1611 | bool FormatsPage::isComplete() const | 1066 | bool FormatsPage::isComplete() const | ||
1612 | { | 1067 | { | ||
1613 | const bool enable = m_isDecimalSymbolOK && m_isDateFormatOK; | 1068 | const bool enable = m_isDecimalSymbolOK && m_isDateFormatOK; | ||
1614 | wizard()->button(QWizard::CustomButton2)->setEnabled(enable); | 1069 | wizard()->button(QWizard::CustomButton2)->setEnabled(enable); | ||
1615 | if (m_wizDlg->m_profileType != CSVWizard::ProfileStockPrices && | 1070 | if (m_imp->m_profile->type() != ProfileStockPrices && | ||
1616 | m_wizDlg->m_profileType != CSVWizard::ProfileCurrencyPrices) | 1071 | m_imp->m_profile->type() != ProfileCurrencyPrices) | ||
1617 | wizard()->button(QWizard::CustomButton3)->setEnabled(enable); | 1072 | wizard()->button(QWizard::CustomButton3)->setEnabled(enable); | ||
1618 | return enable; | 1073 | return enable; | ||
1619 | } | 1074 | } | ||
1620 | 1075 | | |||
1621 | void FormatsPage::cleanupPage() | 1076 | void FormatsPage::cleanupPage() | ||
1622 | { | 1077 | { | ||
1623 | disconnect(ui->comboBox_dateFormat, SIGNAL(currentIndexChanged(int)), this, SLOT(dateFormatChanged(int))); | 1078 | disconnect(ui->comboBox_dateFormat, SIGNAL(currentIndexChanged(int)), this, SLOT(dateFormatChanged(int))); | ||
1624 | disconnect(ui->comboBox_decimalSymbol, SIGNAL(currentIndexChanged(int)), this, SLOT(decimalSymbolChanged(int))); | 1079 | disconnect(ui->comboBox_decimalSymbol, SIGNAL(currentIndexChanged(int)), this, SLOT(decimalSymbolChanged(int))); | ||
1625 | 1080 | | |||
1626 | QList<int> columnList; | 1081 | QList<int> columns = m_imp->getNumericalColumns(); | ||
1627 | if (m_wizDlg->m_profileType == CSVWizard::ProfileBank) { | 1082 | columns.append(m_imp->m_profile->m_colTypeNum.value(ColumnDate)); | ||
1628 | columnList << m_wizDlg->m_pageBanking->m_colTypeNum.value(BankingPage::ColumnDate); | 1083 | m_dlg->clearColumnsBackground(columns); | ||
1629 | if (m_wizDlg->m_pageBanking->m_colTypeNum.value(BankingPage::ColumnAmount) >= 0) | 1084 | m_dlg->m_st = MyMoneyStatement(); // any change on investment/banking page invalidates created statement | ||
1630 | columnList << m_wizDlg->m_pageBanking->m_colTypeNum.value(BankingPage::ColumnAmount); | | |||
1631 | else | | |||
1632 | columnList << m_wizDlg->m_pageBanking->m_colTypeNum.value(BankingPage::ColumnDebit) << | | |||
1633 | m_wizDlg->m_pageBanking->m_colTypeNum.value(BankingPage::ColumnCredit); | | |||
1634 | } else if (m_wizDlg->m_profileType == CSVWizard::ProfileInvest) { | | |||
1635 | columnList << m_wizDlg->m_pageInvestment->m_colTypeNum.value(InvestmentPage::ColumnAmount) << | | |||
1636 | m_wizDlg->m_pageInvestment->m_colTypeNum.value(InvestmentPage::ColumnPrice) << | | |||
1637 | m_wizDlg->m_pageInvestment->m_colTypeNum.value(InvestmentPage::ColumnQuantity) << | | |||
1638 | m_wizDlg->m_pageInvestment->m_colTypeNum.value(InvestmentPage::ColumnDate); | | |||
1639 | if (m_wizDlg->m_pageInvestment->m_colTypeNum.value(InvestmentPage::ColumnFee) != -1) | | |||
1640 | columnList << m_wizDlg->m_pageInvestment->m_colTypeNum.value(InvestmentPage::ColumnFee); | | |||
1641 | } else if (m_wizDlg->m_profileType == CSVWizard::ProfileStockPrices || | | |||
1642 | m_wizDlg->m_profileType == CSVWizard::ProfileCurrencyPrices) { | | |||
1643 | columnList << m_wizDlg->m_pagePrices->m_colTypeNum.value(PricesPage::ColumnPrice) << | | |||
1644 | m_wizDlg->m_pagePrices->m_colTypeNum.value(PricesPage::ColumnDate); | | |||
1645 | } | | |||
1646 | m_wizDlg->clearColumnsBackground(columnList); | | |||
1647 | m_wizDlg->st = MyMoneyStatement(); // any change on investment/banking page invalidates created statement | | |||
1648 | 1085 | | |||
1649 | QList<QWizard::WizardButton> layout; | 1086 | QList<QWizard::WizardButton> layout; | ||
1650 | layout << QWizard::Stretch << | 1087 | layout << QWizard::Stretch << | ||
1651 | QWizard::BackButton << | 1088 | QWizard::BackButton << | ||
1652 | QWizard::NextButton << | 1089 | QWizard::NextButton << | ||
1653 | QWizard::CancelButton; | 1090 | QWizard::CancelButton; | ||
1654 | wizard()->setButtonLayout(layout); | 1091 | wizard()->setButtonLayout(layout); | ||
1655 | } | 1092 | } | ||
1656 | | ||||
1657 | void CSVWizard::closeEvent(QCloseEvent *event) | | |||
1658 | { | | |||
1659 | this->m_plugin->m_action->setEnabled(true); // reenable File->Import->CSV | | |||
1660 | event->accept(); | | |||
1661 | } | | |||
1662 | | ||||
1663 | bool CSVWizard::eventFilter(QObject *object, QEvent *event) | | |||
1664 | { | | |||
1665 | // prevent the QWizard part of CSVWizard window from closing on Escape key press | | |||
1666 | if (object == this->m_wizard) { | | |||
1667 | if (event->type() == QEvent::KeyPress) { | | |||
1668 | QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event); | | |||
1669 | if (keyEvent->key() == Qt::Key_Escape) { | | |||
1670 | close(); | | |||
1671 | return true; | | |||
1672 | } | | |||
1673 | } | | |||
1674 | } | | |||
1675 | return false; | | |||
1676 | } | |