1 /************************************************************************ 2 ** 3 ** Copyright (C) 2015-2021 Kevin B. Hendricks, Stratford, Ontario 4 ** Copyright (C) 2009-2011 Strahinja Markovic <strahinja.markovic@gmail.com> 5 ** 6 ** This file is part of Sigil. 7 ** 8 ** Sigil is free software: you can redistribute it and/or modify 9 ** it under the terms of the GNU General Public License as published by 10 ** the Free Software Foundation, either version 3 of the License, or 11 ** (at your option) any later version. 12 ** 13 ** Sigil is distributed in the hope that it will be useful, 14 ** but WITHOUT ANY WARRANTY; without even the implied warranty of 15 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 ** GNU General Public License for more details. 17 ** 18 ** You should have received a copy of the GNU General Public License 19 ** along with Sigil. If not, see <http://www.gnu.org/licenses/>. 20 ** 21 *************************************************************************/ 22 23 #pragma once 24 #ifndef TABMANAGER_H 25 #define TABMANAGER_H 26 27 #include <QtCore/QUrl> 28 #include <QtWidgets/QTabWidget> 29 30 #include "MainUI/MainWindow.h" 31 #include "Tabs/ContentTab.h" 32 33 class Resource; 34 class HTMLResource; 35 class WellFormedContent; 36 37 /** 38 * Manages the tabs shown in the main UI. 39 * Handles open resource requests, tab switching, closing etc. 40 */ 41 class TabManager : public QTabWidget 42 { 43 Q_OBJECT 44 45 public: 46 47 /** 48 * Constructor. 49 * 50 * @param parent The QObject's parent. 51 */ 52 TabManager(QWidget *parent = 0); 53 54 /** 55 * Returns a reference to the current content tab. 56 * 57 * @return A reference to the current content tab. 58 */ 59 ContentTab *GetCurrentContentTab(); 60 61 QList<ContentTab *> GetContentTabs(); 62 63 QList<Resource *> GetTabResources(); 64 65 QList<Resource *> GetTabResourcesOfType(Resource::ResourceType resource_type); 66 67 int GetTabCount(); 68 69 void CloseAllTabs(bool all=false); 70 void CloseTabForResource(const Resource *resource, bool force=false); 71 72 /** 73 * Returns \c true if all open tabs data is well-formed. 74 * If an issue occurs, user is notified of the problem with a 75 * dialog and the offending tab is switched to automatically. 76 * 77 * @return \c true if the tab data is well-formed. 78 */ 79 bool IsAllTabDataWellFormed(); 80 81 void ReloadTabDataForResources(const QList<Resource *> &resources); 82 83 /** 84 * Close and reopen all tabs 85 */ 86 void ReopenTabs(); 87 88 void UpdateTabDisplay(); 89 90 /** 91 * Close the OPF tab if it's currently open. 92 * Returns true if the OPF had to be closed. 93 */ 94 bool CloseOPFTabIfOpen(); 95 96 public slots: 97 98 /** 99 * Saves any unsaved data in the all the open tabs. 100 */ 101 void SaveTabData(); 102 103 /** 104 * Opens the specified resource in a new tab. 105 * If the resource is already opened, it becomes the current one. 106 * 107 * @param resource - The resource that should be opened. 108 * @param line_to_scroll_to - To which line should the resource scroll (CV). 109 * @param position_to_scroll_to - To which position should the resource scroll (CV). 110 * @param caret_location_to_scroll_to - To which stored caret location should the resource scroll (BV/PV). 111 * @param fragment - The fragment ID to which the new tab should be scrolled to. 112 * @param precede_current_tab - Should the new tab precede the currently opened one. 113 */ 114 void OpenResource(Resource *resource, 115 int line_to_scroll_to = -1, 116 int position_to_scroll_to = -1, 117 const QString &caret_location_to_scroll_to = QString(), 118 const QUrl &fragment = QUrl(), 119 bool precede_current_tab = false); 120 121 /** 122 * Makes the next (right) tab the current one. 123 * Wraps around if necessary. 124 */ 125 void NextTab(); 126 127 /** 128 * Makes the previous (left) tab the current one. 129 * Wraps around if necessary. 130 */ 131 void PreviousTab(); 132 133 /** 134 * Closes the current tab. 135 * If there is only one tab opened, the command is ignored. 136 */ 137 void CloseTab(); 138 139 /** 140 * Removes the current tab, may leave no tabs in windows 141 */ 142 void RemoveTab(); 143 144 /** 145 * Closes all tabs except the current tab. 146 * If there is only one tab opened, the command is ignored. 147 */ 148 void CloseOtherTabs(); 149 150 void CloseOtherTabs(int index); 151 152 /** 153 * Makes the tab the central (shown) tab of the UI. 154 * 155 * @param tab The tab to make central. 156 */ 157 void MakeCentralTab(ContentTab *tab); 158 159 void LinkClicked(const QUrl &url); 160 161 signals: 162 /** 163 * Emitted whenever the user switches from one tab to the next. 164 * 165 * @param old_tab The tab \e from which the user is switching. 166 * @param new_tab The tab \e to which the user is switching. 167 */ 168 void TabChanged(ContentTab *old_tab, ContentTab *new_tab); 169 170 void UpdatePreviewAfterExistingTabSwitch(); 171 172 void TabCountChanged(); 173 174 /** 175 * Emitted whenever one of the tabs wants to open an URL. 176 * 177 * @param url The URL to open. 178 */ 179 void OpenUrlRequest(const QUrl &url); 180 181 /** 182 * Wired to the current FlowTab::OldTabRequest signal. 183 */ 184 void OldTabRequest(QString content, HTMLResource *originating_resource); 185 186 void ShowStatusMessageRequest(const QString &message, int duration = 5000); 187 188 protected: 189 virtual void tabInserted(int index); 190 191 private slots: 192 193 /** 194 * Emits the TabChanged signal. 195 */ 196 void EmitTabChanged(int new_index); 197 198 /** 199 * Deletes the specified tab. 200 * 201 * @param tab_to_delete The tab to delete. 202 */ 203 void DeleteTab(ContentTab *tab_to_delete); 204 205 /** 206 * Closes the tab at the specified index. 207 * If there is only one tab left, the command is ignored. 208 * 209 * @param tab_index The index of the tab to close. 210 * @param force Ignore checks that would prevent a tab from closing. 211 */ 212 void CloseTab(int tab_index, bool force=false); 213 214 /** 215 * Updates the name/header text of the specified tab. 216 * 217 * @param renamed_tab The renamed tab. 218 */ 219 void UpdateTabName(ContentTab *renamed_tab); 220 221 void SetFocusInTab(); 222 223 private: 224 225 /** 226 * Returns the element of the UI that houses well-formed XML data. 227 * 228 * @note CAN BE NULL! This means the main tab has no XML data. 229 * @param index The index of the tab to retrieve. 230 * @return The element with XML data. 231 */ 232 WellFormedContent *GetWellFormedContent(int index); 233 234 /** 235 * Returns the index of tab in which the resource is loaded. 236 * If the resource is not currently loaded, -1 is returned. 237 * 238 * @param resource The resource whose tab index we want. 239 * @return The index of the resource. 240 */ 241 int ResourceTabIndex(const Resource *resource) const; 242 243 /** 244 * Returns true if we have succeeded in switching to the tab of the provided resource. 245 * 246 * @param resource The resource we want to switch to. 247 * @param fragment The fragment ID to which the tab should scroll. 248 * @param line_to_scroll_to To which line should the resource scroll. 249 * @return \c true if we succeeded in switching. 250 */ 251 bool SwitchedToExistingTab(const Resource *resource, 252 int line_to_scroll_to, 253 int position_to_scroll_to, 254 const QString &caret_location_to_scroll_to, 255 const QUrl &fragment); 256 257 /** 258 * Creates a tab for the specified resource. 259 * 260 * @param resource The resource for which we want to create a tab. 261 * @param line_to_scroll_to To which line should the resource scroll. 262 * @param fragment The fragment ID to which the tab should scroll after load. 263 * @return The newly created tab. 264 */ 265 ContentTab *CreateTabForResource(Resource *resource, 266 int line_to_scroll_to, 267 int position_to_scroll_to, 268 const QString &caret_location_to_scroll_to, 269 const QUrl &fragment, 270 bool grab_focus = true); 271 272 /** 273 * Adds a new content tab to the displayed tabs. 274 * If precede_current_tab is false, the new tab is appended 275 * and becomes the current one. Otherwise, it's added just before 276 * the current one and does \e not become the current one. 277 * 278 * @param new_tab The tab to add. 279 * @param precede_current_tab Should the new tab precede the current one. 280 * @return \c true if the tab was successfully added. 281 */ 282 bool AddNewContentTab(ContentTab *new_tab, bool precede_current_tab); 283 284 /////////////////////////////// 285 // PRIVATE MEMBER VARIABLES 286 /////////////////////////////// 287 288 /** 289 * Stores a reference to the tab used before the current one. 290 * Needed for the TabChanged signal. 291 */ 292 ContentTab* m_LastContentTab; 293 294 bool m_CheckWellFormedErrors; 295 296 QList<ContentTab*> m_TabsToDelete; 297 bool m_tabs_deletion_in_use; 298 ContentTab * m_newTab; 299 }; 300 301 #endif // TABMANAGER_H 302 303 304