summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorisanae <14251494+isanae@users.noreply.github.com>2019-07-02 11:05:31 -0400
committerisanae <14251494+isanae@users.noreply.github.com>2019-07-02 11:05:31 -0400
commitc6e80f1a5eed4a57663e7fc55c2727258eaad552 (patch)
tree2c4633f4dc3b912a696d36a52329059fe982321b /src
parent16b6e772a7ae1561ba87c6d76d001b19635761cd (diff)
focus tabs when they need a confirmation to close
dialog did not handle closeEvent() at all, it only checked the close button bunch of comments
Diffstat (limited to 'src')
-rw-r--r--src/modinfodialog.cpp34
-rw-r--r--src/modinfodialog.h6
-rw-r--r--src/modinfodialogtab.cpp5
-rw-r--r--src/modinfodialogtab.h87
-rw-r--r--src/modinfodialogtextfiles.cpp2
5 files changed, 126 insertions, 8 deletions
diff --git a/src/modinfodialog.cpp b/src/modinfodialog.cpp
index b3055b5a..4af479c4 100644
--- a/src/modinfodialog.cpp
+++ b/src/modinfodialog.cpp
@@ -154,7 +154,7 @@ ModInfoDialog::ModInfoDialog(
connect(
tabInfo.tab.get(), &ModInfoDialogTab::originModified,
[this, i](int originID) {
- onOriginModified(static_cast<std::size_t>(i), originID);
+ onOriginModified(originID);
});
connect(
@@ -167,6 +167,15 @@ ModInfoDialog::ModInfoDialog(
connect(
tabInfo.tab.get(), &ModInfoDialogTab::hasDataChanged,
[&]{ setTabsColors(); });
+
+ connect(
+ tabInfo.tab.get(), &ModInfoDialogTab::wantsFocus,
+ [&, i=static_cast<std::size_t>(i)]
+ {
+ if (i < m_tabs.size()) {
+ switchToTab(ETabs(m_tabs[i].tab->tabID()));
+ }
+ });
}
connect(ui->tabWidget, &QTabWidget::currentChanged, [&]{ onTabChanged(); });
@@ -546,6 +555,7 @@ void ModInfoDialog::reAddTabs(const std::vector<bool>& visibility, ETabs sel)
}
+ // removing all tabs
ui->tabWidget->clear();
// reset real positions
@@ -566,7 +576,7 @@ void ModInfoDialog::reAddTabs(const std::vector<bool>& visibility, ETabs sel)
}
}
-void ModInfoDialog::onOriginModified(std::size_t tabIndex, int originID)
+void ModInfoDialog::onOriginModified(int originID)
{
emit originModified(originID);
updateTabs(true);
@@ -581,15 +591,31 @@ void ModInfoDialog::onDeleteShortcut()
}
}
+void ModInfoDialog::closeEvent(QCloseEvent* e)
+{
+ if (tryClose()) {
+ e->accept();
+ } else {
+ e->ignore();
+ }
+}
+
void ModInfoDialog::on_closeButton_clicked()
{
+ if (tryClose()) {
+ close();
+ }
+}
+
+bool ModInfoDialog::tryClose()
+{
for (auto& tabInfo : m_tabs) {
if (!tabInfo.tab->canClose()) {
- return;
+ return false;
}
}
- close();
+ return true;
}
void ModInfoDialog::onTabChanged()
diff --git a/src/modinfodialog.h b/src/modinfodialog.h
index 030b3f93..899a3eab 100644
--- a/src/modinfodialog.h
+++ b/src/modinfodialog.h
@@ -117,6 +117,9 @@ public:
signals:
void originModified(int originID);
+protected:
+ void closeEvent(QCloseEvent* e);
+
private slots:
void on_closeButton_clicked();
void on_nextButton_clicked();
@@ -158,8 +161,9 @@ private:
void switchToTab(ETabs id);
void reAddTabs(const std::vector<bool>& visibility, ETabs sel);
std::vector<QString> getOrderedTabNames() const;
+ bool tryClose();
- void onOriginModified(std::size_t tabIndex, int originID);
+ void onOriginModified(int originID);
void onTabChanged();
void onTabMoved();
diff --git a/src/modinfodialogtab.cpp b/src/modinfodialogtab.cpp
index f5eeeed1..0468b405 100644
--- a/src/modinfodialogtab.cpp
+++ b/src/modinfodialogtab.cpp
@@ -137,6 +137,11 @@ void ModInfoDialogTab::setHasData(bool b)
}
}
+void ModInfoDialogTab::setFocus()
+{
+ emit wantsFocus();
+}
+
NotesTab::NotesTab(
OrganizerCore& oc, PluginContainer& plugin,
diff --git a/src/modinfodialogtab.h b/src/modinfodialogtab.h
index ce29c868..3f98314a 100644
--- a/src/modinfodialogtab.h
+++ b/src/modinfodialogtab.h
@@ -10,6 +10,36 @@ namespace Ui { class ModInfoDialog; }
class Settings;
class OrganizerCore;
+// base class for all tabs in the mod info dialog
+//
+// when the dialog is opened or when next/previous is clicked, the sequence is:
+// setMod(), clear(), feedFile() an update()
+//
+// when the dialog is closed, canClose() is called on all tabs
+//
+// when a tab is selected for the first time for the current mod,
+// firstActivation() is called; this is used by NexusTab to refresh stuff
+//
+// when the dialog is first shown, restoreState() is called on all tabs and
+// saveState() is called when the dialog is closed
+//
+// there isn't a good framework for keyboard shortcuts because only the delete
+// key is used for now, which calls deletedRequested() on all tabs until one
+// returns true
+//
+// each tab override canHandleSeparators() and canHandleUnmanaged() to return
+// true if they can handle separators or unmanaged mods; if these return false
+// (which they do by default), the tabs will be removed from the widget entirely
+//
+// when tabs modify the origin and call emitOriginModified() (such as the
+// conflicts tabs), all tabs that return true in usesOriginFiles() will go
+// through the full update sequence as above
+//
+// tabs can call emitModOpen() to request showing a different mod
+//
+// hasDataChanged() should be called when a tab goes from having data to being
+// empty or vice versa; this will update the tab text color
+//
class ModInfoDialogTab : public QObject
{
Q_OBJECT;
@@ -21,13 +51,63 @@ public:
ModInfoDialogTab& operator=(ModInfoDialogTab&&) = default;
virtual ~ModInfoDialogTab() = default;
+ // called by ModInfoDialog every time this tab is selected; this will call
+ // firstActivation() the first time it's called, until resetFirstActivation()
+ // is called
+ //
void activated();
+
+ // called by ModInfoDialog when the selected mod has changed, to make sure
+ // activated() will call firstActivation() next time
+ //
void resetFirstActivation();
+
+ // called when the selected mod changed, `mod` can never be empty, but
+ // `origin` can (if the mod is not active, for example)
+ //
+ // derived classes can override this to connect to events on the mod for
+ // examples (see NexusTab), but must call the base class implementation
+ //
+ virtual void setMod(ModInfo::Ptr mod, MOShared::FilesOrigin* origin);
+
+ // this tab should clear its user interface; clear() will always be called
+ // before feedFile() and update()
+ //
virtual void clear() = 0;
- virtual void update();
+
+ // the dialog will go through each file in the mod and call feedFile()
+ // with it on all tabs; if a tab handles the file, it should return true to
+ // prevent other tabs from displaying it
+ //
+ // this prevents individual tabs from having to go through the filesystem
+ // independently, which would kill performance, but it cannot be the only way
+ // to update tabs because some of them don't actually use files (like
+ // NotesTab) or they use the internal structures such as `FilesOrigin` (like
+ // ConflictsTab)
+ //
+ // once all the files have been fed to tabs, update() will be called; tabs
+ // that need to do additional work after being fed files, or tabs that are
+ // unable to use feedFile() at all can use update() to do work
+ //
virtual bool feedFile(const QString& rootPath, const QString& filename);
+
+ // called after all the files on the filesystem have been sent through
+ // feedFile()
+ //
+ // this can be used to do a final processing of the files handled by
+ // feedFile() (ImagesTab will set up the scrollbars, for example) or something
+ // completely different (CategoriesTab will fill up the lists)
+ //
+ virtual void update();
+
+ // called when a tab is visible for the first time for the current mod, can
+ // be used to do expensive work that's not worth doing until the tab is
+ // actually selected by the user
+ //
virtual void firstActivation();
+
+ //
virtual bool canClose();
virtual void saveState(Settings& s);
virtual void restoreState(const Settings& s);
@@ -38,8 +118,6 @@ public:
virtual bool canHandleUnmanaged() const;
virtual bool usesOriginFiles() const;
- virtual void setMod(ModInfo::Ptr mod, MOShared::FilesOrigin* origin);
-
ModInfo::Ptr mod() const;
MOShared::FilesOrigin* origin() const;
@@ -50,6 +128,7 @@ signals:
void originModified(int originID);
void modOpen(QString name);
void hasDataChanged();
+ void wantsFocus();
protected:
Ui::ModInfoDialog* ui;
@@ -67,6 +146,8 @@ protected:
void emitModOpen(QString name);
void setHasData(bool b);
+ void setFocus();
+
// this needs to be a template because saveState() and restoreState() are
// not in QWidget, but they're in various widgets
//
diff --git a/src/modinfodialogtextfiles.cpp b/src/modinfodialogtextfiles.cpp
index 52891bf5..bc44ee3e 100644
--- a/src/modinfodialogtextfiles.cpp
+++ b/src/modinfodialogtextfiles.cpp
@@ -133,6 +133,8 @@ bool GenericFilesTab::canClose()
return true;
}
+ setFocus();
+
const int res = QMessageBox::question(
parentWidget(),
QObject::tr("Save changes?"),