1 /* Copyright (c) 2015  Gerald Knizia
2  *
3  * This file is part of the IboView program (see: http://www.iboview.org)
4  *
5  * IboView is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation, version 3.
8  *
9  * IboView is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with bfint (LICENSE). If not, see http://www.gnu.org/licenses/
16  *
17  * Please see IboView documentation in README.txt for:
18  * -- A list of included external software and their licenses. The included
19  *    external software's copyright is not touched by this agreement.
20  * -- Notes on re-distribution and contributions to/further development of
21  *    the IboView software
22  */
23 
24 #include <QSize>
25 #include <QSettings>
26 #include <QMainWindow>
27 #include <QMessageBox>
28 #include <cmath>
29 #include "IvSettings.h"
30 
IvSaveWindowSize(QString Key,QWidget * pWindow)31 void IvSaveWindowSize(QString Key, QWidget *pWindow)
32 {
33    QSettings
34       settings;
35    settings.setValue(Key, pWindow->size());
36 }
37 
38 
IvRestoreWindowSize(QString Key,QWidget * pWindow)39 bool IvRestoreWindowSize(QString Key, QWidget *pWindow)
40 {
41    // restore size of the dialog if it has been saved before.
42    QSettings
43       settings;
44    QSize
45       StoredSize = settings.value(Key).toSize();
46    if (StoredSize.isValid()) {
47       pWindow->resize(StoredSize);
48       // remember that this was not just made up, but actually set up by the user like this.
49       // otherwise there is some logic in some places to GUESS a window size
50       // (see SetDefaultDialogSize)
51       pWindow->setProperty("UserSizeRestored", true);
52       return true;
53    } else
54       return false;
55 }
56 
IvSaveSplitterState(QString Key,QSplitter * pSplitter)57 void IvSaveSplitterState(QString Key, QSplitter *pSplitter)
58 {
59    QSettings
60       settings;
61    settings.setValue(Key, pSplitter->saveState());
62 }
63 
IvRestoreSplitterState(QString Key,QSplitter * pSplitter)64 bool IvRestoreSplitterState(QString Key, QSplitter *pSplitter)
65 {
66    QSettings
67       settings;
68    QByteArray
69       StoredSplitterConfig = settings.value(Key).toByteArray();
70    if (!StoredSplitterConfig.isEmpty()) {
71       pSplitter->restoreState(StoredSplitterConfig);
72       return true;
73    } else
74       return false;
75 }
76 
77 extern QMainWindow *g_pMainWindow; // for usage as dialog parent and for getting reference sizes.
78 
IvGuessSubDialogSize(QWidget * pWindow,double fDefaultVerticalScale)79 void IvGuessSubDialogSize(QWidget *pWindow, double fDefaultVerticalScale)
80 {
81    // make some adjustments to size -- make it relative to parent window size,
82    // to better deal with high DPI displays.
83 
84    // look for a parent object to take the size of. Either the dialog's real parent, or
85    // the main window if it does not have one.
86    QWidget
87       *pParent = pWindow->parentWidget();
88    if (pParent == 0)
89       pParent = g_pMainWindow;
90    if (pParent) {
91       // If the widget has an explicitly set size, do not replace it by our guesswork.
92       QVariant
93          UserSizeRestored = pWindow->property("UserSizeRestored");
94       if (!UserSizeRestored.isValid() || UserSizeRestored.toBool() == false) {
95          if (fDefaultVerticalScale < 0.)
96             fDefaultVerticalScale = 0.8;
97 
98          QSize
99             sz = pWindow->size();
100          if (sz.height() > 0) {
101             double
102                fv = fDefaultVerticalScale*double(pParent->height())/double(sz.height()),
103                fh = std::pow(fv,0.75);
104 
105             // do some further adjustments to prevent making windows wider than their parents.
106             double
107                fDefaultHorizontalScale = 0.7;
108             if (fh*double(sz.width()) > fDefaultHorizontalScale * double(pParent->width())) {
109                fh = fDefaultHorizontalScale*double(pParent->width())/double(sz.width());
110                fv = fh;
111             }
112 
113             if (fh > 1. && fv > 1.) {
114                sz.setHeight(int(sz.height() * fv));
115                sz.setWidth(int(sz.width() * fh));
116                pWindow->resize(sz);
117             }
118          }
119       }
120    }
121 }
122 
123 
IvMakeFileDialogWithHistory(QFileDialog::FileMode FileMode,QFileDialog::AcceptMode AcceptMode,QFileDialog::ViewMode ViewMode,QString HistoryName,QWidget * parent,const QString & caption,const QString & dir,const QString & filter,QString * selectedFilter,QFileDialog::Options options)124 QStringList IvMakeFileDialogWithHistory(QFileDialog::FileMode FileMode, QFileDialog::AcceptMode AcceptMode, QFileDialog::ViewMode ViewMode,  QString HistoryName, QWidget *parent, const QString &caption, const QString &dir, const QString &filter, QString *selectedFilter, QFileDialog::Options options)
125 {
126    QStringList
127       FileNames;
128    QFileDialog
129       FileDialog(parent, caption, QString(), filter);
130 //       FileDialog(parent, caption, QString()); // <- no filter.
131 //       ("./"+dir)
132 //    FileDialog.setFileMode(QFileDialog::AnyFile);
133 //    FileDialog.setAcceptMode(QFileDialog::AcceptSave);
134 //    FileDialog.setViewMode(QFileDialog::Detail);
135    FileDialog.setFileMode(FileMode);
136    FileDialog.setAcceptMode(AcceptMode);
137    FileDialog.setViewMode(ViewMode);
138    FileDialog.setOptions(options);
139    FileDialog.selectFile(dir);
140    QSettings
141       settings;
142    QStringList
143       History;
144    if (!HistoryName.isEmpty()) {
145       History = settings.value(HistoryName).toStringList();
146       if (!History.empty()) {
147          FileDialog.setHistory(History);
148 //          QMessageBox::information(0, "history-in", History.join("\n"));
149       }
150       // ^- this doesn't work... history does not appear anywhere.
151       // my QT version seems to have some other strange behaviors. Like not changing to directories
152       // when directories are selected, but instead asking me to overwrite them. Even though the code in
153       // qfiledialog.cpp clearly checks for this case and looks like it does the right thing
154       // (update: that's because it uses the native dialog... and just emits QDialog::accept() in this case. Gna.).
155       // Maybe this could be hacked via the filesSelected signal, but that could just as well make everything
156       // worse...
157       // UPDATE: doesn't even work. only called after the dialog closes. too late to change at that point.
158    }
159 //    FSaveFileDirChangeProxy
160 //       Dummy(&FileDialog);
161    QString
162       LastPath = settings.value(HistoryName+"Path").toString();
163    if (!LastPath.isEmpty()) {
164       FileDialog.setDirectory(LastPath);
165 //       QMessageBox::information(0, "last path / " + HistoryName+"Path", LastPath);
166    }
167    if (FileDialog.exec()) {
168       FileNames = FileDialog.selectedFiles();
169 
170       if (!HistoryName.isEmpty()) {
171          History = FileDialog.history(); // <- doesn't seem to add files automatically.
172          QString
173             FirstPath;
174          for (int i = 0; i < FileNames.size(); ++ i) {
175             QFileInfo
176                info(FileNames[i]);
177             if (i == 0) FirstPath = info.path();
178             History.insert(0, info.path());
179          }
180          History.removeDuplicates();
181          while (History.size() > 5)
182             History.pop_back(); // QList has no resize method.
183 
184          settings.setValue(HistoryName, History);
185          if (!FirstPath.isEmpty())
186             settings.setValue(HistoryName+"Path", FirstPath);
187       }
188 //          QMessageBox::information(0, "history-out", History.join("\n"));
189       if (selectedFilter)
190          *selectedFilter = FileDialog.selectedNameFilter();
191    }
192    return FileNames;
193 }
194 
IvGetSaveFileName(QString HistoryName,QWidget * parent,const QString & caption,const QString & dir,const QString & filter,QString * selectedFilter,QFileDialog::Options options)195 QString IvGetSaveFileName(QString HistoryName, QWidget *parent, const QString &caption, const QString &dir, const QString &filter, QString *selectedFilter, QFileDialog::Options options)
196 {
197    QStringList
198       FileNames = IvMakeFileDialogWithHistory(QFileDialog::AnyFile, QFileDialog::AcceptSave, QFileDialog::Detail, HistoryName, parent, caption, dir, filter, selectedFilter, options);
199    if (FileNames.size() == 1)
200       return FileNames[0];
201    // cancelled. Note: In mode QFileDialog::AnyFile theoretically the dialog should never return more than one selected file.
202    return QString();
203 }
204 
IvGetOpenFileNames(QString HistoryName,QWidget * parent,const QString & caption,const QString & dir,const QString & filter,QString * selectedFilter,QFileDialog::Options options)205 QStringList IvGetOpenFileNames(QString HistoryName, QWidget *parent, const QString &caption, const QString &dir, const QString &filter, QString *selectedFilter, QFileDialog::Options options)
206 {
207    return IvMakeFileDialogWithHistory(QFileDialog::ExistingFiles, QFileDialog::AcceptOpen, QFileDialog::Detail, HistoryName, parent, caption, dir, filter, selectedFilter, options);
208 }
209