Skip to content

Commit

Permalink
Merge pull request #1307 from JDimproved/implement-external-bbsmenu
Browse files Browse the repository at this point in the history
Implement external BBSMENU
  • Loading branch information
ma8ma committed Dec 23, 2023
2 parents 1864471 + 4af2122 commit 7e0df3a
Show file tree
Hide file tree
Showing 24 changed files with 1,334 additions and 51 deletions.
2 changes: 1 addition & 1 deletion docs/index.md
Expand Up @@ -16,7 +16,7 @@ layout: default
- [マウスジェスチャについて]({{ site.baseurl }}/mouse/)

- [お気に入りについて]({{ site.baseurl }}/favorite/)
- [外部板について]({{ site.baseurl }}/external/)
- [外部板と外部BBSMENUについて]({{ site.baseurl }}/external/)
- [実況モードについて]({{ site.baseurl }}/live/)
- [ユーザーコマンド、リンクフィルタについて]({{ site.baseurl }}/usrcmd/)
- [アスキーアート(AA)の入力について]({{ site.baseurl }}/asciiart/)
Expand Down
18 changes: 17 additions & 1 deletion docs/manual/external.md
@@ -1,5 +1,5 @@
---
title: 外部板について
title: 外部板と外部BBSMENUについて
layout: default
---

Expand All @@ -10,6 +10,7 @@ layout: default
- [現在の対応板](#support)
- [外部板の登録方法](#register)
- [まちBBSのofflaw形式対応について](#machi_offlaw)
- [外部BBSMENUの登録方法](#register_bbsmenu)


<a name="support"></a>
Expand Down Expand Up @@ -43,3 +44,18 @@ offlaw形式での読み込みには以下のような長短がある。

× リモートホストが取得できなくなった<br>
× offlaw形式で読み込んだログは過去のバージョンのJDimでは読めない


<a name="register_bbsmenu"></a>
### 外部BBSMENUの登録方法
<small>v0.10.1-20231223 から追加</small>

外部BBSMENUを登録するには、サイドバーの板一覧の一番上にある「`外部BBSMENU`」フォルダを右クリックして
`外部BBSMENU追加`」を選択し、BBSMENU名とアドレスを入力してOKボタンを押す。
BBSMENUが読み込まれると板一覧の下部に読み込んだ板が追加される。
後からBBSMENUのアドレスや名前を変更する場合は対象のBBSMENUの上で右クリックすると出てくる「`編集`」メニューからおこなう。

設定ファイルのフォーマットは予告なく変更する場合がある。
そのためファイルの編集による登録はサポートしていない。

注意: 実験的なサポートのため変更または廃止の可能性があります。
49 changes: 49 additions & 0 deletions src/bbslist/addetcdialog.cpp
Expand Up @@ -52,3 +52,52 @@ AddEtcDialog::AddEtcDialog( const bool move, const std::string& url, const std::


AddEtcDialog::~AddEtcDialog() noexcept = default;


/** @brief コンストラクタ
*
* @param[in] parent 親ウインドウ (nullable)
* @param[in] edit true なら編集モード
* @param[in] url BBSMENUのURLの初期値
* @param[in] name BBSMENU名前の初期値
*/
AddEtcBBSMenuDialog::AddEtcBBSMenuDialog( Gtk::Window* parent, const bool edit,
const Glib::ustring& url, const Glib::ustring& name )
: SKELETON::PrefDiag{ parent, url, true }
, m_label_supplement{ Glib::ustring{ edit ? "「OK」を押すとBBSMENUをダウンロードして更新します。"
: "「OK」を押すとBBSMENUをダウンロードして板一覧の下部に追加します。" }
+ "\nこの機能は実験的なサポートのため変更または廃止の可能性があります。" }
, m_label_name{ "板名(_N)", true }
, m_label_url{ "アドレス(_U)", true }
{
set_default_size( 600, -1 );

m_label_name.set_alignment( Gtk::ALIGN_START );
m_label_url.set_alignment( Gtk::ALIGN_START );
m_label_name.set_mnemonic_widget( m_entry_name );
m_label_url.set_mnemonic_widget( m_entry_url );

m_entry_name.set_hexpand( true );
m_entry_url.set_hexpand( true );
m_entry_name.set_text( name );
m_entry_url.set_text( url );

m_grid.set_column_spacing( 8 );
m_grid.set_row_spacing( 8 );
m_grid.attach( m_label_name, 0, 0, 1, 1 );
m_grid.attach( m_entry_name, 1, 0, 1, 1 );
m_grid.attach( m_label_url, 0, 1, 1, 1 );
m_grid.attach( m_entry_url, 1, 1, 1, 1 );

get_content_area()->set_spacing( 8 );
get_content_area()->property_margin() = 8;
get_content_area()->pack_start( m_label_supplement );
get_content_area()->pack_start( m_grid );

set_activate_entry( m_entry_name );
set_activate_entry( m_entry_url );

set_title( edit ? "外部BBSMENU編集" : "外部BBSMENU追加" );

show_all_children();
}
26 changes: 25 additions & 1 deletion src/bbslist/addetcdialog.h
Expand Up @@ -30,8 +30,32 @@ namespace BBSLIST
std::string get_url() const { return m_entry_url.get_text(); }
std::string get_id() const { return m_entry_id.get_text(); }
std::string get_passwd() const { return m_entry_pw.get_text(); }
};
};


/**
* @brief 外部BBSMENUを追加/編集するダイアログ
*/
class AddEtcBBSMenuDialog : public SKELETON::PrefDiag
{
/// @brief タイトルと入力欄だけでは分かりにくいため補足説明をつける
Gtk::Label m_label_supplement;

Gtk::Label m_label_name;
Gtk::Label m_label_url;
Gtk::Entry m_entry_name;
Gtk::Entry m_entry_url;

Gtk::Grid m_grid;

public:

AddEtcBBSMenuDialog( Gtk::Window* parent, const bool edit, const Glib::ustring& url, const Glib::ustring& name );
~AddEtcBBSMenuDialog() noexcept = default;

std::string get_name() const { return m_entry_name.get_text(); }
std::string get_url() const { return m_entry_url.get_text(); }
};
}

#endif
127 changes: 118 additions & 9 deletions src/bbslist/bbslistview.cpp
Expand Up @@ -8,6 +8,7 @@

#include "skeleton/msgdiag.h"

#include "dbtree/bbsmenu.h"
#include "dbtree/interface.h"

#include "config/globalconf.h"
Expand Down Expand Up @@ -48,7 +49,7 @@ BBSListViewMain::~BBSListViewMain()
void BBSListViewMain::save_xml()
{
const std::string file = CACHE::path_xml_listmain();
constexpr std::string_view remove_dirs[] = { SUBDIR_ETCLIST };
constexpr std::string_view remove_dirs[] = { SUBDIR_ETCLIST, SUBDIR_BBSMENU };
save_xml_impl( file, ROOT_NODE_NAME, remove_dirs );
}

Expand Down Expand Up @@ -112,6 +113,62 @@ void BBSListViewMain::update_view()

// 外部板追加ここまで
//----------------------------------
// 外部BBSMENU追加

// <subdir>を挿入
// ルート要素の有無で処理を分ける( 旧様式=無, 新様式=有 )
if( root ) subdir = root->emplace_front( XML::NODE_TYPE_ELEMENT, "subdir" );
else subdir = get_document().emplace_front( XML::NODE_TYPE_ELEMENT, "subdir" );
subdir->setAttribute( "name", SUBDIR_BBSMENU );

// 子要素( <bbsmenu> )を追加
if( const auto& vec_bbsmenu = DBTREE::get_bbsmenus(); // 外部BBSMENU情報( dbtree/bbsmenu.h )
! vec_bbsmenu.empty() ) {
for( const DBTREE::BBSMenu& info : vec_bbsmenu ) {
const std::string& info_name = info.get_name();
const std::string& info_url = info.get_url();

// 外部BBSMENUに追加
XML::Dom* bbsmenu = subdir->appendChild( XML::NODE_TYPE_ELEMENT, "bbsmenu" );
bbsmenu->setAttribute( "name", info_name );
bbsmenu->setAttribute( "url", info_url );

// <subdir>を板一覧の末尾に追加
// ルート要素の有無で処理を分ける( 旧様式=無, 新様式=有 )
XML::Dom* bbsmenu_subdir = root ? root->appendChild( XML::NODE_TYPE_ELEMENT, "subdir" )
: get_document().appendChild( XML::NODE_TYPE_ELEMENT, "subdir" );
bbsmenu_subdir->setAttribute( "name", info_name );
bbsmenu_subdir->setAttribute( "url", info_url );
bbsmenu_subdir->setAttribute( "data", "nosave" ); // 外部BBSMENUの板は個別に保存する

std::list<XML::Dom*> boardlist = info.xml_document().getElementsByTagName( "boardlist" );
if( boardlist.empty() ) continue;
const XML::Dom* categories = boardlist.front();

// カテゴリのサブディレクトリを作成してその中に板を追加していく
for( const XML::Dom* category_in : *categories ) {
const std::string category_name = category_in->getAttribute( "name" );
if( category_name.empty() ) continue;

XML::Dom* category_subdir = bbsmenu_subdir->appendChild( XML::NODE_TYPE_ELEMENT, "subdir" );
category_subdir->setAttribute( "name", category_name );
category_subdir->setAttribute( "url", category_in->getAttribute( "url" ) );
category_subdir->setAttribute( "dirid", category_in->getAttribute( "dirid" ) );

for( const XML::Dom* board_in : *category_in ) {
const std::string board_name = board_in->getAttribute( "name" );
if( board_name.empty() ) continue;

XML::Dom* node_board = category_subdir->appendChild( XML::NODE_TYPE_ELEMENT, "board" );
node_board->setAttribute( "name", board_name );
node_board->setAttribute( "url", board_in->getAttribute( "url" ) );
}
}
}
}

// 外部BBSMENU追加ここまで
//----------------------------------

// BBSListViewBase::xml2tree() m_document -> tree
xml2tree( std::string( ROOT_NODE_NAME ) );
Expand Down Expand Up @@ -149,7 +206,13 @@ void BBSListViewMain::delete_view_impl()
std::cout << "BBSListViewMain::delete_view_impl\n";
#endif

// データベースから外部板削除
constexpr const int kDeleteTargetBoard = 0b01;
constexpr const int kDeleteTargetBBSMenu = 0b10;
int delete_target = 0;

std::vector<Gtk::TreeIter> delete_bbsmenu_iterators;

// データベースから外部板または外部BBSMENUを削除
std::list< Gtk::TreeModel::iterator > list_it = get_treeview().get_selected_iterators();
for( Gtk::TreeModel::iterator& iter : list_it ) {
if( is_etcboard( iter ) ) {
Expand All @@ -163,14 +226,50 @@ void BBSListViewMain::delete_view_impl()
<< "name = " << name << std::endl;
#endif
DBTREE::remove_etc( url , name );
delete_target |= kDeleteTargetBoard;
}
else if( is_bbsmenu( iter ) ) {
const std::string url = row2url( *iter );
const std::string name = row2name( *iter );

DBTREE::remove_bbsmenu( url, name );
delete_target |= kDeleteTargetBBSMenu;

// 板一覧の下部に追加した外部BBSMENUの板一覧を削除するためにイテレーターを記憶する
auto it = get_treestore()->get_iter( "0" );
while( it ) {
auto row_url = row2url( *it );
auto row_name = row2name( *it );
auto row_type = row2type( *it );
if( row_type == TYPE_DIR && row_url == url && row_name == name ) {
delete_bbsmenu_iterators.push_back( std::move( *it ) );
break;
}
++it;
}
}
}

const bool force = true; // 強制的に削除
get_treeview().delete_selected_rows( force );

// etc.txt保存
DBTREE::save_etc();
// 板一覧の下部に追加した外部BBSMENUの板一覧を削除する
if( ! delete_bbsmenu_iterators.empty() ) {
// 取得したTreeStoreのイテレーターが壊れないように後ろから削除していく
auto rend = delete_bbsmenu_iterators.rend();
for( auto rit = delete_bbsmenu_iterators.rbegin(); rit != rend; ++rit ) {
get_treestore()->erase( *rit );
}
}

if( delete_target & kDeleteTargetBoard ) {
// etc.txt保存
DBTREE::save_etc();
}
if( delete_target & kDeleteTargetBBSMenu ) {
// bbsmenu.txt保存
DBTREE::save_bbsmenu();
}
}


Expand Down Expand Up @@ -217,20 +316,30 @@ Gtk::Menu* BBSListViewMain::get_popupmenu( const std::string& url )

if( type == TYPE_DIR ){
if( is_etcdir( path ) ) popupmenu = id2popupmenu( "popup_menu_etcdir" );
else if( is_bbsmenudir( path ) ) popupmenu = id2popupmenu( "popup_menu_bbsmenudir" );
else popupmenu = id2popupmenu( "popup_menu_dir" );
}
else if( type == TYPE_BOARD || type == TYPE_BOARD_UPDATE ){
if( is_etcboard( path ) ) popupmenu = id2popupmenu( "popup_menu_etc" );
else popupmenu = id2popupmenu( "popup_menu" );
}
else if( type == TYPE_BBSMENU ) {
if( is_bbsmenu( path ) ) popupmenu = id2popupmenu( "popup_menu_bbsmenu" );
else popupmenu = id2popupmenu( "popup_menu" );
}
}
else{
bool have_bbsmenu = true;
bool have_etc = true;
for( const Gtk::TreeIter& iter : list_it ) {
if( ! is_bbsmenu( iter ) ) have_bbsmenu = false;
if( ! is_etcboard( iter ) ) have_etc = false;

const bool have_etc = std::all_of( list_it.cbegin(), list_it.cend(),
[this]( const Gtk::TreeIter& iter ) { return is_etcboard( iter ); } );

if( have_etc ) popupmenu = id2popupmenu( "popup_menu_mul_etc" );
else popupmenu = id2popupmenu( "popup_menu_mul" );
if( ! have_bbsmenu && ! have_etc ) break;
}
if( have_bbsmenu ) popupmenu = id2popupmenu( "popup_menu_mul_bbsmenu" );
else if( have_etc ) popupmenu = id2popupmenu( "popup_menu_mul_etc" );
else popupmenu = id2popupmenu( "popup_menu_mul" );
}

return popupmenu;
Expand Down

0 comments on commit 7e0df3a

Please sign in to comment.